[![Discord](./Images/TOR_server.png)](https://discord.gg/77RkMJHWsM)
-![eisbison infographic](./Images/TOR_roles.jpg)
+![eisbison infographic](./Images/TOR_Roles.png)
# The Other Roles
-The **The Other Roles**, is a mod for [Among Us](https://store.steampowered.com/app/945360/Among_Us) which adds many new roles, new [Settings](#settings), new [Custom Hats](#custom-hats) and support for [10+ Player Lobbies](#Custom-Servers-and-10+-Players) to the game.
-Even more roles are coming soon :)
+The **The Other Roles**, is a mod for [Among Us](https://store.steampowered.com/app/945360/Among_Us) which adds many new roles, new [Settings](#settings) and new [Custom Hats](#custom-hats) to the game.
+Even more roles are coming soon. :)
-| Impostors | Crewmates | Neutral | Secondary |
+| Impostors | Crewmates | Neutral | Modifier |
|----------|-------------|-----------------|----------------|
-| [Evil Mini](#mini) | [Nice Mini](#mini) | [Arsonist](#arsonist) | [Lover](#lovers) |
-| [Evil Guesser](#guesser) | [Nice Guesser](#guesser) | [Jester](#jester) | |
-| [Bounty Hunter](#bounty-hunter) | [Detective](#detective) | [Jackal](#jackal) | |
-| [Camouflager](#camouflager) | [Engineer](#engineer) | [Sidekick](#sidekick) | |
-| [Cleaner](#cleaner) | [Hacker](#hacker) | [Vulture](#vulture) | |
-| [Eraser](#eraser) | [Lighter](#lighter) | [Lawyer](#lawyer) | |
-| [Godfather (Mafia)](#mafia) | [Mayor](#mayor) | | |
-| [Mafioso (Mafia)](#mafia) | [Medic](#medic) | | |
-| [Janitor (Mafia)](#mafia) | [Security Guard](#security-guard) | | |
-| [Morphling](#morphling) | [Seer](#seer) | | |
-| [Trickster](#trickster) | [Sheriff](#sheriff)
-| [Vampire](#vampire) | [Deputy](#deputy) | |
-| [Warlock](#warlock) | [Shifter](#shifter) | | |
-| [Witch](#witch) | [Snitch](#snitch) | | |
+| [Godfather (Mafia)](#mafia) | [Shifter](#shifter) | [Jester](#jester) | [Bloody](#bloody) |
+| [Mafioso (Mafia)](#mafia) | [Mayor](#mayor) | [Arsonist](#arsonist) | [Anti Teleport](#anti-teleport) |
+| [Janitor (Mafia)](#mafia) | [Engineer](#engineer) | [Jackal](#jackal) | [Tie Breaker](#tie-breaker) |
+| [Morphling](#morphling) | [Sheriff](#sheriff) | [Sidekick](#sidekick) | [Bait](#bait) |
+| [Camouflager](#camouflager) | [Deputy](#deputy) | [Vulture](#vulture) | [Lovers](#lovers) |
+| [Vampire](#vampire) | [Lighter](#lighter) | [Lawyer](#lawyer) | [Sunglasses](#sunglasses) |
+| [Eraser](#eraser) | [Detective](#detective) | | [Mini](#mini) |
+| [Trickster](#trickster) | [Time Master](#time-master) | | [VIP](#vip) |
+| [Cleaner](#cleaner) | [Medic](#medic) | | [Invert](#invert) |
+| [Warlock](#warlock) | [Swapper](#swapper) |
+| [Bounty Hunter](#bounty-hunter) | [Seer](#seer) | |
+| [Witch](#witch) | [Hacker](#hacker) | | |
+| [Ninja](#ninja) | [Tracker](#tracker) | | |
+| [Evil Guesser](#guesser) | [Snitch](#snitch) | | |
| | [Spy](#spy) | | |
-| | [Swapper](#swapper) | | |
-| | [Time Master](#time-master) | | |
-| | [Tracker](#tracker) | | |
-| | [Bait](#bait) | |
-| | [Medium](#medium) | |
+| | [Portalmaker](#portalmaker) | | |
+| | [Security Guard](#security-guard) | | |
+| | [Medium](#medium) | | |
+| | [Nice Guesser](#guesser) | |
The [Role Assignment](#role-assignment) sections explains how the roles are being distributed among the players.
# Releases
| Among Us - Version| Mod Version | Link |
|----------|-------------|-----------------|
+| 2022.3.29| v4.0.0| [Download](https://github.com/Eisbison/TheOtherRoles/releases/download/v4.0.0/TheOtherRoles.zip)
| 2022.3.29s| v3.4.5| [Download](https://github.com/Eisbison/TheOtherRoles/releases/download/v3.4.5/TheOtherRoles.zip)
| 2022.2.23s| v3.4.4| [Download](https://github.com/Eisbison/TheOtherRoles/releases/download/v3.4.4/TheOtherRoles.zip)
| 2021.12.15s| v3.4.3| [Download](https://github.com/Eisbison/TheOtherRoles/releases/download/v3.4.3/TheOtherRoles.zip)
@@ -101,6 +101,25 @@ The [Role Assignment](#role-assignment) sections explains how the roles are bein
Click to show the Changelog
+**Version 4.0.0**
+- Added new role [Ninja](#ninja) thanks [gendelo3](https://github.com/gendelo3)
+- Added new role [Portalmaker](#portalmaker) thanks [gendelo3](https://github.com/gendelo3)
+- Added option Shield Last Round First Kill (until the first meeting)
+- Added option that medic shield will be set instantly, but shows up after meeting
+- Added additions to Swapper (charges mechanic, confirm swap button, UI & color changes in meeting)
+- Added option Mayor can always see the vote color (after finishing x-amount of tasks)
+- Added possibility to enter a name
+- Added map in meeting with last position and list of tasks
+- Added Bait, Mini, Lover, Bloody, Sunglasses, Anti Teleport, Tiebreaker & Invert modifier
+- Changed lobby/settings ui
+- Changed that a sidekicked Spy/Impostor is still shown red to Impostor
+- Changed the position of the Guesser to The Neutral Roles (Guesser still remains Imp/Crew when setting up roles)
+- Reworked the Lawyer
+- Removed Bait, Mini & Lover role
+- Fixed a bug with the color of the scream robe
+- Fixed a bug where the Jack In The Box size was not properly on Airship
+- Fixed a bug where "No vote is self vote" did not work
+
**Version 3.4.5**
- Update to Among Us version 2022.3.29s
- Added horse-mode button in the main menu (bottom right)
@@ -110,7 +129,7 @@ The [Role Assignment](#role-assignment) sections explains how the roles are bein
- Fixed a bug where the killer doesn't teleport to the body
- Changed the light source to prevent vanilla bugs
- Removed dlekS (for now) :c
-
+
**Version 3.4.4**
- Fixed a bug where games were not finished properly on offical servers (special thanks to miniduikboot & 6pak)
@@ -595,16 +614,21 @@ docker run -d -p 22023:22023/udp --env IMPOSTOR_AntiCheat__Enabled=false --env I
# Settings
The mod adds a few new settings to Among Us (in addition to the role settings):
- **Streamer Mode:** You can activate the streamer mode in the Among Us settings. It hides the lobby code, the custom server ip and the custom server port. You can set a custom lobby code replacement text, by changing the *Streamer Mode Replacement Text* in the `BepInEx\config\me.eisbison.theotherroles.cfg` file.
-- **Number of Impostors:** The number of Impostor count be set inside a lobby
-- **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)
+- **Number of Crewmates:** The number of Crewmate roles can be set inside a lobby.
+- **Number of Neutrals:** The number of Neutral roles can be set inside a lobby.
+- **Number of Impostors:** The number of Impostor roles can be set inside a lobby.
+- **Number of Modifiers:** The number of Modifiers can be set inside a lobby.
+- **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, they'll vote themself.
- **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 also see the name of the Spy and everyone can still see the age of the mini.
-- **Allow Parallel MedBay Scans:** Allows players to perform their MedBay scans at the same time
+- **Allow Parallel MedBay Scans:** Allows players to perform their MedBay scans at the same time.
+- **Shield Last Game First Kill** The first killed player of the previous round will be shielded for all players visible until the first meeting.
+- **Play On A Random Map** If enabled it allows you to set a rotation of all current maps, except ehT dlekS
- **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.
+- **The map is accessable during a meeting and will show your last location when a body gets reported/meeting gets called**
- **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
- **Darker/Lighter:** Displays color type of each player in meetings
@@ -695,7 +719,7 @@ The Janitor is an Impostor who cannot kill, but they can hide dead bodies instea
## Morphling
### **Team: Impostors**
-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.
+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 Mini when they copy its look.
@@ -715,8 +739,8 @@ The Morphling is an Impostor which can additionally scan the appearance of a pla
## Camouflager
### **Team: Impostors**
-The Camouflager is an Impostor which can additionally activate a camouflage mode.
-The camouflage mode lasts for 10s and while it is active, all player names/pets/hats
+The Camouflager is an Impostor which can additionally activate a camouflage mode.\
+The camouflage mode lasts for 10s and while it is active, all player names/pets/hats\
are hidden and all players have the same color.\
\
**NOTE:**
@@ -760,8 +784,8 @@ The Eraser is an Impostor that can erase the role of every player.\
The targeted players will lose their role after the meeting right before a player is exiled.\
After every erase, the cooldown increases by 10 seconds.\
The erase will be performed, even if the Eraser or their target die before the next meeting.\
-By default the Eraser can erase everyone but the Spy and other Impostors. Depending on the options
-they can also erase them (Impostors will lose their special Impostor ability).
+By default the Eraser can erase everyone but the Spy and other Impostors.\
+Depending on the options they can also erase them (Impostors will lose their special Impostor ability).\
\
**NOTE:**
- The Shifter shift will always be triggered before the Erase (hence either the new role of the Shifter will be erased or the Shifter saves the role of their target, depending on whom the Eraser erased)
@@ -780,10 +804,9 @@ ex-Lover surviving, as the partnership was erased before. Also a Jester win woul
## Trickster
### **Team: Impostors**
-The Trickster is an Impostor that can place 3 jack-in-the-boxes that are invisible at first to other players. \
-If the Trickster has placed all of their boxes they will be converted into a vent network usable only by the Trickster themself, but the boxes are revealed to the others. \
+The Trickster is an Impostor that can place 3 jack-in-the-boxes that are invisible at first to other players.\
+If the Trickster has placed all of their boxes they will be converted into a vent network usable only by the Trickster themself, but the boxes are revealed to the others.\
If the boxes are converted to a vent network, the Trickster gains a new ability "Lights out" to limit the visibility of Non-Impostors, that cannot be fixed by other players. Lights are automatically restored after a while.\
-
\
**NOTE:**
- Impostors will get a text indicator at the bottom of the screen to notify them if the lights are out due to the Trickster ability, as there is no sabotage arrows or task to sabotage text to otherwise notify them about it.
@@ -800,7 +823,6 @@ If the boxes are converted to a vent network, the Trickster gains a new ability
## Cleaner
### **Team: Impostors**
The Cleaner is an Impostor who has the ability to clean up dead bodies.\
-
\
**NOTE:**
- The Kill and Clean cooldown are shared, preventing them from immediately cleaning their own kills.
@@ -813,14 +835,12 @@ The Cleaner is an Impostor who has the ability to clean up dead bodies.\
| Cleaner Cooldown | Cooldown for cleaning dead bodies
-----------------------
-
## Warlock
### **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 they are).\
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.\
-
\
**NOTE:**
- The Warlock can always kill their Impostor mates (and even themself) using the "cursed kill"
@@ -835,7 +855,6 @@ The Warlock can still perform normal kills, but the two buttons share the same c
| Warlock Root Time | Time the Warlock is rooted in place after killing using the curse
-----------------------
-
## Bounty Hunter
### **Team: Impostors**
\
@@ -869,12 +888,10 @@ Similar to the Vampire, shields and blanks will be checked twice (at the end of
This can result in players being marked as spelled during the meeting, but not dying in the end (when they get a shield or the Witch gets blanked after they were spelled by the Witch).\
If the Witch dies before the meeting starts or if the Witch is being guessed during the meeting, the spellbound players will be highlighted but they'll survive in any case.\
Depending on the options you can choose whether voting the Witch out will save all the spellbound players or not.\
-
\
**NOTE:**
- The spellbound players will die before the voted player dies (which might trigger e.g. trigger an Impostor win condition, even if the Witch is the one being voted)
-
### Game Options
| Name | Description |
|----------|:-------------:|
@@ -887,6 +904,29 @@ Depending on the options you can choose whether voting the Witch out will save a
| Voting The Witch Saves All The Targets | If set to true, all the cursed targets will survive at the end of the meeting
-----------------------
+## Ninja
+### **Team: Impostors**
+The Ninja is an Impostor who has the ability to kill another player all over the map.\
+You can mark a player with your ability and by using the ability again, you jump to the position of the marked player and kill it.\
+Depending on the options you know where your marked player is.\
+If the Ninja uses its ability, it will leave a trace (leaves) for a configurable amount of time where it activated the ability and additionally where it killed the before marked player.\
+\
+**NOTE:**
+- The Ninja has a 5 second cooldown after marking a player
+- The trace has a darker (black) or lighter (white) color depending on the players color that will fade into green
+- The mark on the marked player will reset after a meeting or after using the ability to kill the marked player. Performing a normal kill will **NOT** reset the mark
+- If the Ninja tries to kill a shielded player (e.g. Medic shield, Shield last game first kill ), the kill will not be performed
+- If the Ninja tries to kill the Time Master while the shield is active, the Ninja won't teleport to the players position, but the Time Master shield will still be activated
+
+### Game Options
+| Name | Description |
+|----------|:-------------:|
+| Ninja Spawn Chance | -
+| Ninja Mark Cooldown | -
+| Ninja Knows Location Of Target | -
+| Trace Duration | -
+| Time Till Trace Color Has Faded | -
+-----------------------
## Guesser
### **Team: Crewmates or Impostors**
@@ -918,126 +958,198 @@ Depending on the options, the Guesser can't guess the shielded player and depend
-----------------------
-## Lovers
-### **Team: Lovers (and secondary team)**
-There are always two Lovers which are linked together.\
-Their primary goal is it to stay alive together until the end of the game.\
-If one Lover dies (and the option is activated), the other Lover suicides.\
-You can select if Lovers are able to have a second role (could be a Neutral, Crewmate or Impostor Role)\
-You can specify the chance of one Lover being an Impostor.\
-The Lovers never know the role of their partner, they only see who their partner is.\
-The Lovers win, if they are both alive when the game ends. They can also win with their original team (e.g. a dead Impostor Lover can win with the Impostors, an Arsonist Lover can still achieve an Arsonist win)\
-If one of the Lovers is a killer (i.e. Jackal/Sidekick/Impostor), they can achieve a "Lovers solo win" where only the Lovers win.\
-If there is no killer among the Lovers (e.g. an Arsonist Lover + Crewmate Lover) and they are both alive when the game ends, they win together with the Crewmates.\
-If there's a team Impostor/Jackal Lover in the game, the tasks of a Crewmate Lover won't be counted (for a task win) as long as they're alive. If the Lover dies, their tasks will also be counted.\
-You can enable an exclusive chat only for Lovers\
-\
-**NOTE:**
-- In a 2 Cremates vs 2 Impostors (or 2 members of team Jackal) and the Lovers are not in the same team, the game is not automatically over since the Lovers can still achieve a solo win. E.g. if there are the following roles Impostor + ImpLover + Lover + Crewmate left, the game will not end and the next kill will decide if the Impostors or Lovers win.
-- The Lovers can change if the Shifter takes the role of a Lovers
+## Jester
+### **Team: Neutral**
+The Jester does not have any tasks. They win the game as a solo, if they get voted out during a meeting.
### Game Options
| Name | Description |
|----------|:-------------:|
-| Lovers Spawn Chance | -
-| Chance That One Lover Is Impostor | -
-| Both Lovers Die | Whether the second Lover suicides, if the first one dies
-| Lovers Can Have Another Role | If set to true, the Lovers can have a second role
-| Enable Lover Chat | -
+| Jester Spawn Chance | -
+| Jester Can Call Emergency Meeting | Option to disable the emergency button for the Jester
-----------------------
+## Arsonist
+### **Team: Neutral**
+The Arsonist does not have any tasks, they have to win the game as a solo.\
+The Arsonist can douse other players by pressing the douse button and remaining next to the player for a few seconds.\
+If the player that the Arsonist douses walks out of range, the cooldown will reset to 0.\
+After dousing everyone alive the Arsonist can ignite all the players which results in an Arsonist win.
-## Sheriff
-### **Team: Crewmates**
-The Sheriff has the ability to kill Impostors.
-If they try to kill a Crewmate, they die instead.
+### Game Options
+| Name | Description |
+|----------|:-------------:|
+| Arsonist Spawn Chance | -
+| Arsonist Countdown | -
+| Arsonist Douse Duration | The time it takes to douse a player
+-----------------------
+
+## Jackal
+### **Team: Jackal**
+The Jackal is part of an extra team, that tries to eliminate all the other players.\
+The Jackal has no tasks and can kill Impostors, Crewmates and Neutrals.\
+The Jackal (if allowed by the options) can select another player to be their Sidekick.
+Creating a Sidekick removes all tasks of the Sidekick and adds them to the team Jackal. The Sidekick loses their current role (except if they're a Lover, then they play in two teams).
+The "Create Sidekick Action" may only be used once per Jackal or once per game (depending on the options).
+The Jackal can also promote Impostors to be their Sidekick, but depending on the options the Impostor will either really turn into the Sidekick and leave the team Impostors or they will just look like the Sidekick to the Jackal and remain as they were.\
+Also if a Spy or Impostor gets sidekicked, they still will appear red to the Impostors.
+
+The team Jackal enables multiple new outcomes of the game, listing some examples here:
+- The Impostors could be eliminated and then the crew plays against the team Jackal.
+- 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 Mini lose by vote
+2. Jester wins by vote
+3. Arsonist win
+4. Team Impostor wins by sabotage
+5. Team Crew wins by tasks (also possible if the whole Crew is dead)
+6. Lovers among the last three players win
+7. Team Jackal wins by outnumbering (When the team Jackal contains an equal or greater amount of players than the Crew and there are 0 Impostors left and team Jackal contains no Lover)
+8. Team Impostor wins by outnumbering (When the team Impostors contains an equal or greater amount of players than the Crew and there are 0 players of the team Jackal left and team Impostors contains no Lover)
+9. Team Crew wins by outnumbering (When there is no player of the team Jackal and the team Impostors left)
**NOTE:**
-- If the Sheriff shoots the person the Medic shielded, the Sheriff and the shielded person **both remain unharmed**.
-- 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.
+- The Jackal (and their Sidekick) may be killed by a Sheriff.
+- A Jackal cannot target the Mini, while it's growing up. After that they 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.
### Game Options
-| Name | Description |
+| Name | Description
|----------|:-------------:|
-| Sheriff Spawn Chance | -
-| Sheriff Cooldown | -
-| Sheriff Can Kill Neutrals | -
-| Sheriff Has A Deputy | Deputy can not be in game without Sheriff
+| Jackal Spawn Chance | - |
+| Jackal/Sidekick Kill Cooldown | Kill cooldown |
+| Jackal Create Sidekick Cooldown | Cooldown before a Sidekick can be created |
+| Jackal can use vents | Yes/No |
+| Jackal can create a Sidekick | Yes/No |
+| Jackals promoted from Sidekick can create a Sidekick | Yes/No (to prevent the Jackal team from growing) |
+| Jackals can make an Impostor to their Sidekick | Yes/No (to prevent a Jackal from turning an Impostor into a Sidekick, if they use the ability on an Impostor they see the Impostor as Sidekick, but the Impostor isn't converted to Sidekick. If this option is set to "No" Jackal and Sidekick can kill each other.) |
+| Jackal and Sidekick have Impostor vision | - |
-----------------------
-## Deputy
-### **Team: Crewmates**
-The Deputy has the ability to handcuff player.
-Handcuffs will be hidden until the handcuffed player try to use a disabled button/hotkey.
-Handcuffs disable:
-- Kill
-- Abilities
-- Vent
-- Report
-
+## Sidekick
+### **Team: Jackal**
+Gets assigned to a player during the game by the "Create Sidekick Action" of the Jackal and joins the Jackal in their quest to eliminate all other players.\
+Upon the death of the Jackal (depending on the options), they might get promoted to Jackal themself and potentially even assign a Sidekick of their own.\
+\
**NOTE:**
-- Duration starts after the handcuffs become visible.
-- Deputy can not be in game without Sheriff.
+- A player that converts into a Sidekick loses their previous role and tasks (if they had one).
+- The Sidekick may be killed by a Sheriff.
+- The Sidekick cannot target the Mini, while it's growing up.
### Game Options
-| Name | Description |
+| Name | Description
|----------|:-------------:|
-| Deputy Number Of Handcuffs | -
-| Handcuff Cooldown| -
-| Handcuff Duration | -
-| Sheriff And Deputy Know Each Other | -
-| Deputy Gets Promoted To Sheriff | "Off", "On (Immediately)" or "On (After Meeting)"
-| Deputy Keeps Handcuffs When Promoted |-
+| Jackal/Sidekick Kill Cooldown | Uses the same kill cooldown setting as the Jackal |
+| Sidekick gets promoted to Jackal on Jackal death | Yes/No |
+| Sidekick can kill | Yes/No |
+| Sidekick can use vents | Yes/No |
-----------------------
-## Jester
+## Vulture
### **Team: Neutral**
-The Jester does not have any tasks. They win the game as a solo, if they get voted out during a meeting.
+
+The Vulture does not have any tasks, they have to win the game as a solo.\
+The Vulture is a neutral role that must eat a specified number of corpses (depending on the options) in order to win.\
+Depending on the options, when a player dies, the Vulture gets an arrow pointing to the corpse.\
+If there is a Vulture in the game, there can't be a Cleaner.
### Game Options
| Name | Description |
|----------|:-------------:|
-| Jester Spawn Chance | -
-| Jester Can Call Emergency Meeting | Option to disable the emergency button for the Jester
+| Vulture Spawn Chance | -
+| Vulture Countdown | -
+| Number Of Corpses Needed To Be Eaten | Corpes needed to be eaten to win the game
+| Vulture Can Use Vents | -
+| Show Arrows Pointing Towards The Corpes | -
-----------------------
-## Arsonist
+## Lawyer
### **Team: Neutral**
-The Arsonist does not have any tasks, they have to win the game as a solo.\
-The Arsonist can douse other players by pressing the douse button and remaining next to the player for a few seconds.\
-If the player that the Arsonist douses walks out of range, the cooldown will reset to 0.\
-After dousing everyone alive the Arsonist can ignite all the players which results in an Arsonist win.
+The Lawyer is a neutral role that has a client.\
+The client might be an Impostor or Jackal which is no Lover.\
+Depending on the options, the client can also be a Jester.\
+The Lawyer needs their client to win in order to win the game.\
+Their client doesn't know that it is their client.\
+If their client gets voted out, the Lawyer dies with the client.\
+If their client dies, the Lawyer changes their role and becomes the [Pursuer](#pursuer), which has a different goal to win the game.\
+\
+How the Lawyer wins:
+- Lawyer dead/alive, client alive and client wins: The Lawyer wins together with the team of the client.
+- If their client is Jester and the Jester gets voted out, the Lawyer wins together with the Jester.
+
+**NOTE:**
+- If the client disconnects, the Lawyer will also turn into the Pursuer
+- The Lawyer needs to figure out the role of their client depending on the options
### Game Options
| Name | Description |
|----------|:-------------:|
-| Arsonist Spawn Chance | -
-| Arsonist Countdown | -
-| Arsonist Douse Duration | The time it takes to douse a player
+| Lawyer Spawn Chance | -
+| Lawyer Target Can Be The Jester | -
+| Lawyer Wins After Meetings | If set to true, the Lawyer wins after a configurable amount of meetings (can't start meetings himself)
+| Lawyer Needed Meetings To Win | -
+| Lawyer Vision | Pursuer has normal vision
+| Lawyer Knows Target Role | -
+| Pursuer Blank Cooldown | -
+| Pursuer Number Of Blanks | -
-----------------------
-## Seer
+## Pursuer
+### **Team: Neutral**
+The Pursuer is still a neutral role, but has a different goal to win the game; they have to be alive when the game ends and the Crew wins.\
+In order to achieve this goal, the Pursuer has an ability called "Blank", where they can fill a killers (this also includes the Sheriff) weapon with a blank. So, if the killer attempts to kill someone, the killer will miss their target, and their cooldowns will be triggered as usual.\
+If the killer fires the "Blank", shields (e.g. Medic shield or Time Master shield) will not be triggered.\
+The Pursuer has tasks (which can already be done while being a Lawyer), that count towards the task win for the Crewmates. If the Pursuer dies, their tasks won't be counted anymore.
+
+-----------------------
+
+## Shifter
### **Team: Crewmates**
-The Seer has two abilities (one can activate one of them or both in the options).
-The Seer sees the souls of players that died a round earlier, the souls slowly fade away.
-The Seer gets a blue flash on their screen, if a player dies somewhere on the map.
+The Shifter can take over the role of another Crewmate, the other player will transform into a Crewmate.\
+The Shift will always be performed at the end of the next meeting right before a player is exiled. The target needs to be chosen during the round.\
+Even if the Shifter or the target dies before the meeting, the Shift will still be performed.\
+Swapping roles with an Impostor or Neutral fails and the Shifter commits suicide after the next meeting (there won't be any body).\
+The Shifter aims to save roles from leaving the game, by e.g. taking over a Sheriff or Medic that is known to the Impostors.\
+This works especially well against the Eraser, but also gives the Eraser the possibility to act like a Shifter.\
+The **special interactions** with the Shifter are noted in the chapters of the respective roles.\
+\
+**NOTE:**
+- The Shifter shift will always be triggered before the Erase (hence either the new role of the Shifter will be erased or the Shifter saves the role of their target, depending on whom the Eraser erased)
+- If the Shifter takes over a role, their new cooldowns will start at the maximum cooldown of the ability
+- One time use abilities (e.g. shielding a player or Engineer sabotage fix) can only used by one player in the game (i.e. the Shifter
+can only use them, if the previous player did not use them before)
+
+### Game Options
+| Name | Description
+|----------|:-------------:|
+| Shifter Spawn Chance | -
+| Shifter Shifts Modifiers | Sets if Lovers and/or Medic Shield will be shifted
+-----------------------
+
+## Mayor
+### **Team: Crewmates**
+The Mayor leads the Crewmates by having a vote that counts twice.\
+The Mayor can always use their meeting, even if the maximum number of meetings was reached.\
+The Mayor can see the vote colors after completing a configurable amount of tasks, depending on the options.
### Game Options
| Name | Description |
|----------|:-------------:|
-| Seer Spawn Chance | -
-| Seer Mode | Options: Show death flash and souls, show death flash, show souls
-| Seer Limit Soul Duration | Toggle if souls should turn invisible after a while
-| Seer Soul Duration | Sets how long it will take the souls to turn invisible after a meeting
+| Mayor Spawn Chance | -
+| Mayor Can See Vote Colors | -
+| Mayor Completed Tasks Needed To See Vote Colors | -
-----------------------
## Engineer
### **Team: Crewmates**
The Engineer (if alive) can fix a certain amount of sabotages per game from anywhere on the map.\
The Engineer can use vents.\
-If the Engineer is inside a vent, depending on the options the members of the team Jackal/Impostors will see a blue outline around all vents on the map (in order to warn them).
-Because of the vents the Engineer might not be able to start some tasks using the "Use" button, you can double-click on the tasks instead.\
-\
+If the Engineer is inside a vent, depending on the options the members of the team Jackal/Impostors will see a blue outline around all vents on the map (in order to warn them).\
+Because of the vents the Engineer might not be able to start some tasks using the "Use" button, you can double-click on the tasks instead.
+
**NOTE:**
- The kill button of Impostors activates if they stand next to a vent where the Engineer is. They can also kill them there. No other action (e.g. Morphling sample, Shifter shift, ...) can affect players inside vents.
@@ -1050,26 +1162,47 @@ Because of the vents the Engineer might not be able to start some tasks using th
| Jackal and Sidekick See Vents Highlighted | -
-----------------------
-## Detective
+## Sheriff
### **Team: Crewmates**
-The Detective can see footprints that other players leave behind.
-The Detective's other feature shows when they report a corpse: they receive clues about the killer's identity. The type of information they get is based on the time it took them to find the corpse.
+The Sheriff has the ability to kill Impostors.\
+If they try to kill a Crewmate, they die instead.\
\
**NOTE:**
-- When people change their colors (because of a morph or camouflage), all the footprints also change their colors (also the ones that were already on the ground). If the effects are over, all footprints switch back to the original color.
-- The Detective does not see footprints of players that sit in vents
-- More information about the [colors](#colors)
-- During the meetings you can see, whether a player wears a darker or a lighter color, represented by (D) or (L) in the names.
+- If the Sheriff shoots the person the Medic shielded, the Sheriff and the shielded person **both remain unharmed**.
+- 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 |
|----------|:-------------:|
-| Detective Spawn Chance | -
-| Anonymous Footprints | If set to true, all footprints will have the same color. Otherwise they will have the color of the respective player.
-| Footprint Interval | The interval between two footprints
-| Footprint Duration | Sets how long the footprints remain visible.
-| Time Where Detective Reports Will Have Name | The amount of time that the Detective will have to report the body since death to get the killer's name. |
-| Time Where Detective Reports Will Have Color Type| The amount of time that the Detective will have to report the body since death to get the killer's color type. |
+| Sheriff Spawn Chance | -
+| Sheriff Cooldown | -
+| Sheriff Can Kill Neutrals | -
+| Sheriff Has A Deputy | Deputy can not be in game without Sheriff
+-----------------------
+
+## Deputy
+### **Team: Crewmates**
+The Deputy has the ability to handcuff player.\
+Handcuffs will be hidden until the handcuffed player try to use a disabled button/hotkey.\
+Handcuffs disable:
+- Kill
+- Abilities
+- Vent
+- Report\
+\
+**NOTE:**
+- Duration starts after the handcuffs become visible.
+- Deputy can not be in game without Sheriff.
+
+### Game Options
+| Name | Description |
+|----------|:-------------:|
+| Deputy Number Of Handcuffs | -
+| Handcuff Cooldown| -
+| Handcuff Duration | -
+| Sheriff And Deputy Know Each Other | -
+| Deputy Gets Promoted To Sheriff | "Off", "On (Immediately)" or "On (After Meeting)"
+| Deputy Keeps Handcuffs When Promoted |-
-----------------------
## Lighter
@@ -1086,80 +1219,125 @@ The Lighter can turn on their Lighter every now and then, which increases their
| Lighter Duration | -
-----------------------
-## Mini
-### **Team: Crewmates or Impostors**
-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 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.
+## Detective
+### **Team: Crewmates**
+The Detective can see footprints that other players leave behind.\
+The Detective's other feature shows when they report a corpse: they receive clues about the killer's identity. The type of information they get is based on the time it took them to find the corpse.
**NOTE:**
-- If the Sheriff tries to kill the Mini before it's fully grown, they die, no matter if the Mini is a Crewmate or Impostor
-- The Sheriff can kill the Impostor Mini, but only if it's fully grown up
+- When people change their colors (because of a morph or camouflage), all the footprints also change their colors (also the ones that were already on the ground). If the effects are over, all footprints switch back to the original color.
+- The Detective does not see footprints of players that sit in vents
+- More information about the [colors](#colors)
### Game Options
| Name | Description |
|----------|:-------------:|
-| Mini Spawn Chance | -
-| Mini | Mini Growing Up Duration
+| Detective Spawn Chance | -
+| Anonymous Footprints | If set to true, all footprints will have the same color. Otherwise they will have the color of the respective player.
+| Footprint Interval | The interval between two footprints
+| Footprint Duration | Sets how long the footprints remain visible.
+| Time Where Detective Reports Will Have Name | The amount of time that the Detective will have to report the body since death to get the killer's name. |
+| Time Where Detective Reports Will Have Color Type| The amount of time that the Detective will have to report the body since death to get the killer's color type. |
-----------------------
-## Medic
+## Time Master
### **Team: Crewmates**
-The Medic can shield (highlighted by an outline around the player) one player per game, which makes the player unkillable.\
-The shielded player can still be voted out and might also be an Impostor.\
-If set in the options, the shielded player and/or the Medic will get a red flash on their screen if someone (Impostor, Sheriff, ...) tried to murder them.
+The Time Master has a time shield which they can activate. The time shield remains active for a configurable amount of time.\
+If a player tries to kill the Time Master while the time shield is active, the kill won't happen and the
+time will rewind for a set amount of time.\
+The kill cooldown of the killer won't be reset, so the Time Master
+has to make sure that the game won't result in the same situation.\
+The Time Master won't be affected by the rewind.
+
+**NOTE:**
+- Only the movement is affected by the rewind.
+- A Vampire bite will trigger the rewind. If the Time Master misses shielding the bite, they can still shield the kill which happens a few seconds later.
+- If the Time Master was bitten and has their shield active before when a meeting is called, they survive but the time won't be rewound.
+- If the Time Master has a Medic shield, they won't rewind.
+- The shield itself ends immediately when triggered. So the Time Master can be attacked again as soon as the rewind ends.
+
+### Game Options
+| Name | Description |
+|----------|:-------------:|
+| Time Master Spawn Chance | - |
+| Time Master Cooldown | - |
+| Rewind Duration | How much time to rewind |
+| Time Master Shield Duration |
+-----------------------
+
+## Medic
+### **Team: Crewmates**
+The Medic can shield (highlighted by an outline around the player) one player per game, which makes the player unkillable.\
+The shielded player can still be voted out and might also be an Impostor.\
+If set in the options, the shielded player and/or the Medic will get a red flash on their screen if someone (Impostor, Sheriff, ...) tried to murder them.\
If the Medic dies, the shield disappears with them.\
The Sheriff will not die if they try to kill a shielded Crewmate and won't perform a kill if they try to kill a shielded Impostor.\
Depending on the options, guesses from the Guesser will be blocked by the shield and the shielded player/medic might be notified.\
The Medic's other feature shows when they report a corpse: they will see how long ago the player died.
-\
+
**NOTE:**
- If the shielded player is a Lover and the other Lover dies, they nevertheless kill themselves.
- If the Shifter has a shield or their target has a Shield, the shielded player switches.
- Shields set after the next meeting, will be set before a possible shift is being performed.
-
### Game Options
| Name | Description | Options |
|----------|:-------------:|:-------------:|
| Medic Spawn Chance | - | -
| Show Shielded Player | Sets who sees if a player has a shield | "Everyone", "Shielded + Medic", "Medic"
| Shielded Player Sees Murder Attempt| Whether a shielded player sees if someone tries to kill them | True/false |
-| Shield Will Be Set After Next Meeting | - | True/false
+| Shield Will Be Activated | Sets when the shield will be active | "Instantly", "Instantly, Visible After Meeting", "After Meeting"
| Medic Sees Murder Attempt On Shielded Player | - | If anyone tries to harm the shielded player (Impostor, Sheriff, Guesser, ...), the Medic will see a red flash
-----------------------
-## Mayor
+## Swapper
### **Team: Crewmates**
-The Mayor leads the Crewmates by having a vote that counts twice.\
-The Mayor can always use their meeting, even if the maximum number of meetings was reached.
+During meetings the Swapper can exchange votes that two people get (i.e. all votes
+that player A got will be given to player B and vice versa).\
+Because of the Swapper's strength in meetings, they might not start emergency meetings and can't fix lights and comms.\
+The Swapper now has initial swap charges and can recharge those charges after completing a configurable amount of tasks.\
+\
+**NOTE:**
+- The remaining charges will be displayed in brackets next to the players role while not in a meeting
+- In a meeting the charges will appear next to the Confirm Swap button
+
+### Game Options
+| Name | Description
+|----------|:-------------:|
+| Swapper Spawn Chance | -
+| Swapper can call emergency meeting | Option to disable the emergency button for the Swapper
+| Swapper can only swap others | Sets whether the Swapper can swap themself or not
+| Initial Swap Charges | -
+| Number Of Tasks Needed For Recharging | -
+-----------------------
+
+## Seer
+### **Team: Crewmates**
+The Seer has two abilities (one can activate one of them or both in the options).\
+The Seer sees the souls of players that died a round earlier, the souls slowly fade away.\
+The Seer gets a blue flash on their screen, if a player dies somewhere on the map.
### Game Options
| Name | Description |
|----------|:-------------:|
-| Mayor Spawn Chance | -
+| Seer Spawn Chance | -
+| Seer Mode | Options: Show death flash and souls, show death flash, show souls
+| Seer Limit Soul Duration | Toggle if souls should turn invisible after a while
+| Seer Soul Duration | Sets how long it will take the souls to turn invisible after a meeting
-----------------------
## Hacker
### **Team: Crewmates**
If the Hacker activates the "Hacker mode", the Hacker gets more information than others from the admin table and vitals for a set duration.\
-Otherwise they see the same information as everyone else.
+Otherwise they see the same information as everyone else.\
**Admin table:** The Hacker can see the colors (or color types) of the players on the table.\
**Vitals**: The Hacker can see how long dead players have been dead for.\
The Hacker can access his mobile gadgets (vitals & admin table), with a maximum of charges (uses) and a configurable amount of tasks needed to recharge.\
-While accessing those mobile gadgets, the Hacker is not able to move.\
-\
+While accessing those mobile gadgets, the Hacker is not able to move.
+
**NOTE:**
- If the Morphling morphs or the Camouflager camouflages, the colors on the admin table change accordingly
- More information about the [colors](#colors)
-- During the meetings you can see, whether a player wears a darker or a lighter color, represented by (D) or (L) in the names.
### Game Options
| Name | Description |
@@ -1173,75 +1351,11 @@ While accessing those mobile gadgets, the Hacker is not able to move.\
| Can't Move During Cam Duration | -
-----------------------
-
-## Shifter
-### **Team: Crewmates**
-The Shifter can take over the role of another Crewmate, the other player will transform into a Crewmate.\
-The Shift will always be performed at the end of the next meeting right before a player is exiled. The target needs to be chosen during the round.\
-Even if the Shifter or the target dies before the meeting, the Shift will still be performed.\
-Swapping roles with an Impostor or Neutral fails and the Shifter commits suicide after the next meeting (there won't be any body).\
-The Shifter aims to save roles from leaving the game, by e.g. taking over a Sheriff or Medic that is known to the Impostors.\
-This works especially well against the Eraser, but also gives the Eraser the possibility to act like a Shifter.\
-The **special interactions** with the Shifter are noted in the chapters of the respective roles.\
-\
-**NOTE:**
-- The Shifter shift will always be triggered before the Erase (hence either the new role of the Shifter will be erased or the Shifter saves the role of their target, depending on whom the Eraser erased)
-- If the Shifter takes over a role, their new cooldowns will start at the maximum cooldown of the ability
-- One time use abilities (e.g. shielding a player or Engineer sabotage fix) can only used by one player in the game (i.e. the Shifter
-can only use them, if the previous player did not use them before)
-
-### Game Options
-| Name | Description
-|----------|:-------------:|
-| Shifter Spawn Chance | -
-| Shifter Shifts Modifiers | Sets if Lovers and/or Medic Shield will be shifted
------------------------
-
-## Time Master
-### **Team: Crewmates**
-The Time Master has a time shield which they can activate. The time shield remains active for a configurable amount of time.\
-If a player tries to kill the Time Master while the time shield is active, the kill won't happen and the
-time will rewind for a set amount of time.\
-The kill cooldown of the killer won't be reset, so the Time Master
-has to make sure that the game won't result in the same situation.\
-The Time Master won't be affected by the rewind.\
-\
-**NOTE:**
-- Only the movement is affected by the rewind.
-- A Vampire bite will trigger the rewind. If the Time Master misses shielding the bite, they can still shield the kill which happens a few seconds later.
-- If the Time Master was bitten and has their shield active before when a meeting is called, they survive but the time won't be rewound.
-- If the Time Master has a Medic shield, they won't rewind.
-- The shield itself ends immediately when triggered. So the Time Master can be attacked again as soon as the rewind ends.
-
-### Game Options
-| Name | Description |
-|----------|:-------------:|
-| Time Master Spawn Chance | - |
-| Time Master Cooldown | - |
-| Rewind Duration | How much time to rewind |
-| Time Master Shield Duration |
------------------------
-
-## Swapper
-### **Team: Crewmates**
-During meetings the Swapper can exchange votes that two people get (i.e. all votes
-that player A got will be given to player B and vice versa).\
-Because of the Swapper's strength in meetings, they might not start emergency meetings
-and can't fix lights and comms.
-
-### Game Options
-| Name | Description
-|----------|:-------------:|
-| Swapper Spawn Chance | -
-| Swapper can call emergency meeting | Option to disable the emergency button for the Swapper
-| Swapper can only swap others | Sets whether the Swapper can swap themself or not
------------------------
-
## Tracker
### **Team: Crewmates**
-The Tracker can select one player to track. Depending on the options the Tracker can track a different person after each meeting or the Tracker tracks the same person for the whole game.
-An arrow points to the last tracked position of the player.
-The arrow updates its position every few seconds (configurable).
+The Tracker can select one player to track. Depending on the options the Tracker can track a different person after each meeting or the Tracker tracks the same person for the whole game.\
+An arrow points to the last tracked position of the player.\
+The arrow updates its position every few seconds (configurable).\
Depending on the options, the Tracker has another ability: They can track all corpses on the map for a set amount of time. They will keep tracking corpses, even if they were cleaned or eaten by the Vulture.
### Game Options
@@ -1257,10 +1371,9 @@ Depending on the options, the Tracker has another ability: They can track all co
## Snitch
### **Team: Crewmates**
-When the Snitch finishes all the tasks, arrows will appear (only visible to the Snitch) that point to the Impostors (depending on the options also to members of team Jackal).
+When the Snitch finishes all the tasks, arrows will appear (only visible to the Snitch) that point to the Impostors (depending on the options also to members of team Jackal).\
When the Snitch has one task left (configurable) the Snitch will be revealed to the Impostors (depending on the options also to members of team Jackal) with an arrow pointing to the Snitch.
-
### Game Options
| Name | Description
|----------|:-------------:|
@@ -1271,71 +1384,6 @@ When the Snitch has one task left (configurable) the Snitch will be revealed to
| Snitch can't be guessed after finishing all their tasks | -
-----------------------
-## Jackal
-### **Team: Jackal**
-The Jackal is part of an extra team, that tries to eliminate all the other players.\
-The Jackal has no tasks and can kill Impostors, Crewmates and Neutrals.\
-The Jackal (if allowed by the options) can select another player to be their Sidekick.
-Creating a Sidekick removes all tasks of the Sidekick and adds them to the team Jackal. The Sidekick loses their current role (except if they're a Lover, then they play in two teams).
-The "Create Sidekick Action" may only be used once per Jackal or once per game (depending on the options).
-The Jackal can also promote Impostors to be their Sidekick but, depending on the options the Impostor will either really turn into the Sidekick and leave the team Impostors or they will just look like the Sidekick to the Jackal and remain as they were.\
-\
-The team Jackal enables multiple new outcomes of the game, listing some examples here:
-- The Impostors could be eliminated and then the crew plays against the team Jackal.
-- 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 Mini lose by vote
-2. Jester wins by vote
-3. Arsonist win
-4. Team Impostor wins by sabotage
-5. Team Crew wins by tasks (also possible if the whole Crew is dead)
-6. Lovers among the last three players win
-7. Team Jackal wins by outnumbering (When the team Jackal contains an equal or greater amount of players than the Crew and there are 0 Impostors left and team Jackal contains no Lover)
-8. Team Impostor wins by outnumbering (When the team Impostors contains an equal or greater amount of players than the Crew and there are 0 players of the team Jackal left and team Impostors contains no Lover)
-9. Team Crew wins by outnumbering (When there is no player of the team Jackal and the team Impostors left)
-
-**NOTE:**
-- The Jackal (and their Sidekick) may be killed by a Sheriff.
-- A Jackal cannot target the Mini, while it's growing up. After that they 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.
-
-
-
-### Game Options
-| Name | Description
-|----------|:-------------:|
-| Jackal Spawn Chance | - |
-| Jackal/Sidekick Kill Cooldown | Kill cooldown |
-| Jackal Create Sidekick Cooldown | Cooldown before a Sidekick can be created |
-| Jackal can use vents | Yes/No |
-| Jackal can create a Sidekick | Yes/No |
-| Jackals promoted from Sidekick can create a Sidekick | Yes/No (to prevent the Jackal team from growing) |
-| Jackals can make an Impostor to their Sidekick | Yes/No (to prevent a Jackal from turning an Impostor into a Sidekick, if they use the ability on an Impostor they see the Impostor as Sidekick, but the Impostor isn't converted to Sidekick. If this option is set to "No" Jackal and Sidekick can kill each other.) |
-| Jackal and Sidekick have Impostor vision | - |
------------------------
-
-## Sidekick
-### **Team: Jackal**
-Gets assigned to a player during the game by the "Create Sidekick Action" of the Jackal and joins the Jackal in their quest to eliminate all other players.\
-Upon the death of the Jackal (depending on the options), they might get promoted to Jackal themself and potentially even assign a Sidekick of their own.
-\
-**NOTE:**
-- A player that converts into a Sidekick loses their previous role and tasks (if they had one), except the Lover role.
-- The Sidekick may be killed by a Sheriff.
-- The Sidekick cannot target the Mini, while it's growing up.
-
-### Game Options
-| Name | Description
-|----------|:-------------:|
-| Jackal/Sidekick Kill Cooldown | Uses the same kill cooldown setting as the Jackal |
-| Sidekick gets promoted to Jackal on Jackal death | Yes/No |
-| Sidekick can kill | Yes/No |
-| Sidekick can use vents | Yes/No |
------------------------
-
## Spy
### **Team: Crewmates**
The Spy is a Crewmate, which has no special abilities.\
@@ -1345,6 +1393,9 @@ There are two possibilities (depending on the set options):
- The Impostors can kill the Spy but they can also kill their Impostor partner (if they mistake another Impostor for the Spy)
You can set whether the Sheriff can kill the Spy or not (in order to keep the lie alive).
+**NOTE:**
+- If the Spy gets sidekicked, it still will appear red to the Impostors.
+
### Game Options
| Name | Description
|----------|:-------------:|
@@ -1355,13 +1406,37 @@ You can set whether the Sheriff can kill the Spy or not (in order to keep the li
| Spy Has Impostor Vision | Give the Spy the same vision as the Impostors have
-----------------------
+## Portalmaker
+### **Team: Crewmates**
+The Portalmaker is a Crewmate that can place two portals on the map.\
+These two portals are connected to each other.\
+Those portals will be visible after the next meeting and can be used by everyone.\
+Additionally to that, the Portalmaker gets information about who used the portals and when in the chat during each meeting, depending on the options.
+
+**NOTE:**
+- The extra button to use a portal will appear after the Portalmaker set his portals and a meeting/body report was called.
+- While one player uses a portal, it is blocked for any other player until the player got teleported.
+- All ghosts can still use the portals, but won't block any living player from using it and the Portalmaker won't get any information about it in chat.
+- If a morphed person uses a portal it will show the morphed name/color depending on the options.
+- If a comouflaged person uses a portal it will show "A comouflaged person used the portal."
+
+### Game Options
+| Name | Description
+|----------|:-------------:|
+| Portalmaker Spawn Chance | -
+| Portalmaker Cooldown | -
+| Use Portal Cooldown | -
+| Portalmaker Log Only Shows Color Type | -
+| Log Shows Time | -
+-----------------------
+
## Security Guard
### **Team: Crewmates**
The Security Guard is a Crewmate that has a certain number of screws that they can use for either sealing vents or for placing new cameras.\
Placing a new camera and sealing vents takes a configurable amount of screws. The total number of screws that a Security Guard has can also be configured.\
The new camera will be visible after the next meeting and accessible by everyone.\
-The vents will be sealed after the next meeting, players can't enter or exit sealed vents, but they can still "move to them" underground.\
-\
+The vents will be sealed after the next meeting, players can't enter or exit sealed vents, but they can still "move to them" underground.
+
**NOTE:**
- Trickster boxes can't be sealed
@@ -1385,27 +1460,10 @@ The vents will be sealed after the next meeting, players can't enter or exit sea
| Can't Move During Cam Duration | -
-----------------------
-## Bait
-### **Team: Crewmates**
-
-The Bait is a Crewmate that if killed, forces the killer to self report the body (you can configure a delay in the options).
-Additionally, the Bait can see if someone is inside a vent (depending on the options the exact vent gets
-an outline or all vents do).
-
-### Game Options
-| Name | Description
-|----------|:-------------:|
-| Bait Spawn Chance | -
-| Bait Highlight All Vents | If set to true, all vents will be highlighted if a player is inside of one of them. If set to false, only the vents where players are siting in will be highlighted.
-| Bait Report Delay | -
-| Warn The Killer With A Flash | -
------------------------
-
## Medium
### **Team: Crewmates**
-The medium is a crewmate who can ask the souls of dead players for information. Like the Seer, it sees the places where the players have died (after the next meeting) and can question them. It then gets random information about the soul or the killer in the chat. The souls only stay for one round, i.e. until the next meeting. Depending on the options, the souls can only be questioned once and then disappear.
-During the meetings you can see, whether a player wears a darker or a lighter color, represented by (D) or (L) in the names.
+The medium is a crewmate who can ask the souls of dead players for information. Like the Seer, it sees the places where the players have died (after the next meeting) and can question them. It then gets random information about the soul or the killer in the chat. The souls only stay for one round, i.e. until the next meeting. Depending on the options, the souls can only be questioned once and then disappear.\
Questions:
What is your Role?
@@ -1422,58 +1480,163 @@ What is your killers role? (mini exluded)
| Medium Each Soul Can Only Be Questioned Once | If set to true, souls can only be questioned once and then disappear
-----------------------
-## Vulture
-### **Team: Neutral**
+# Modifier
+A modifier is an addition to your Impostor/Neutral/Crewmate role.
-The Vulture does not have any tasks, they have to win the game as a solo.\
-The Vulture is a neutral role that must eat a specified number of corpses (depending on the options) in order to win.\
-Depending on the options, when a player dies, the Vulture gets an arrow pointing to the corpse.
-If there is a Vulture in the game, there can't be a Cleaner.
+## Bloody
+### Bloody
+
+If killed, the Bloody Modifier will leave a trail for x-seconds on their killer. The trail will have the color of the killed person. Impostor,
+Neutral or Crewmate roles can have this Modifier.
### Game Options
| Name | Description |
|----------|:-------------:|
-| Vulture Spawn Chance | -
-| Vulture Countdown | -
-| Number Of Corpses Needed To Be Eaten | Corpes needed to be eaten to win the game
-| Vulture Can Use Vents | -
-| Show Arrows Pointing Towards The Corpes | -
+| Bloody Spawn Chance | -
+| Bloody Quantity | -
+| Trail duration | -
-----------------------
-## Lawyer
-### **Team: Neutral**
-The Lawyer is a neutral role that has a client.
-The client might be an Impostor or Jackal which is no Lover.
-The Lawyer needs their client to win in order to win the game.
-If their client dies or gets voted out, the Lawyer changes their role and becomes the [Pursuer](#pursuer), which has a different goal to win the game.
-The main goal of the Lawyer is to win as Lawyer, as it is not allowed to betray their client.
+## Anti Teleport
-The Lawyer can win in multiple ways:
-- Lawyer dead, client alive and client team won: The Lawyer wins together with the team of the client
-- Lawyer and client alive and client team won: The Lawyer wins with the team of the client. The client **doesn't** win (even if their Impostor/Team Jackal mate wins), the Lawyer steals their win. Hence the client should keep the Lawyer alive for some time, to get some help during the meetings, but has to eliminate them soon enough to not get their win stolen.
+The Anti Teleport Modifier prevents the player from getting teleported to the Meeting Table if a body gets reported or an Emergency Meeting is called.\
+The player will start the round where the previous one ended (Emergency Meeting Call/Body Report).
+
+### Game Options
+| Name | Description |
+|----------|:-------------:|
+| Anti Teleport Spawn Chance | -
+| Anti Teleport Quantity | -
+-----------------------
+
+## Tie Breaker
+
+If the Voting ends in a tie, the Tie Breaker takes place and the player with the Tie Breaker Modifier gets an extra vote thats not visible to anyone.\
+Everyone will know if the Tie Breaker was involved in the Meeting or not.
+
+### Game Options
+| Name | Description |
+|----------|:-------------:|
+| Tie Breaker Spawn Chance | -
+-----------------------
+
+## Bait
+
+The Bait forces the killer to self report the body (you can configure a delay in the options).\
+There can be more than one Bait.
+
+### Game Options
+| Name | Description
+|----------|:-------------:|
+| Bait Spawn Chance | -
+| Bait Quantity | -
+| Bait Report Delay Min | -
+| Bait Report Delay Max | -
+| Warn The Killer With A Flash | -
+-----------------------
+
+## Lovers
+
+There are always two Lovers which are linked together.\
+Their primary goal is it to stay alive together until the end of the game.\
+If one Lover dies (and the option is activated), the other Lover suicides.\
+You can specify the chance of one Lover being an Impostor.\
+The Lovers never know the role of their partner, they only see who their partner is.\
+The Lovers win, if they are both alive when the game ends. They can also win with their original team (e.g. a dead Impostor Lover can win with the Impostors, an Arsonist Lover can still achieve an Arsonist win).\
+If one of the Lovers is a killer (i.e. Jackal/Sidekick/Impostor), they can achieve a "Lovers solo win" where only the Lovers win.\
+If there is no killer among the Lovers (e.g. an Arsonist Lover + Crewmate Lover) and they are both alive when the game ends, they win together with the Crewmates.\
+If there's an Impostor/Jackal + Crewmate Lover in the game, the tasks of a Crewmate Lover won't be counted (for a task win) as long as they're alive.\
+If the Lover dies, their tasks will also be counted.\
+You can enable an exclusive chat only for Lovers.
**NOTE:**
-- If the client disconnects, the Lawyer will also turn into the Pursuer
-- If "Lawyer Target Knows" is set to true, the client will know that someone is their Lawyer, but won't know who.
+In a 2 Crewmates vs 2 Impostors (or 2 members of team Jackal) and the Lovers are not in the same team, the game is not automatically over since the Lovers can still achieve a solo win. E.g. if there are the following roles Impostor + ImpLover + Lover + Crewmate left, the game will not end and the next kill will decide if the Impostors or Lovers win.
### Game Options
| Name | Description |
|----------|:-------------:|
-| Lawyer Target Knows | The target knows that it is the target (marked with "§", if the Lawyer dies, the mark will disappear)
-| Lawyer Wins After Meetings | If set to true, the Lawyer wins after a configurable amount of meetings (can't start meetings himself)
-| Lawyer Needed Meetings To Win | -
-| Lawyer Vision | Pursuer has normal vision
-| Lawyer Knows Target Role | -
-| Pursuer Blank Cooldown | -
-| Pursuer Number Of Blanks | -
+| Lovers Spawn Chance | -
+| Chance That One Lover Is Impostor | -
+| Both Lovers Die | Whether the second Lover suicides, if the first one dies
+| Enable Lover Chat | -
-----------------------
-## Pursuer
-### **Team: Neutral**
-The Pursuer is still a neutral role, but has a different goal to win the game; they have to be alive when the game ends (no matter who causes the win).
-In order to achieve this goal, the Pursuer has an ability called "Blank", where they can fill a killers (this also includes the Sheriff) weapon with a blank. So, if the killer attempts to kill someone, the killer will miss their target, and their cooldowns will be triggered as usual.
-If the killer fires the "Blank", shields (e.g. Medic shield or Time Master shield) will not be triggered.
-The Pursuer has tasks (which can already be done while being a Lawyer), that count towards the task win for the Crewmates. If the Pursuer dies, their tasks won't be counted anymore.
+## Sunglasses
+
+The Sunglasses will lower the Crewmate's vision by small percentage. The percentage is configurable in the options.\
+The vision will also be affected when lights out.
+
+**NOTE:**
+- Sunglasses only affects Crewmates.
+- If you have the Sunglasses modifier and get sidekicked, you lose the modifier.
+
+### Game Options
+| Name | Description
+|----------|:-------------:|
+| Sunglasses Spawn Chance | -
+| Sunglasses Quantity | -
+| Vision with sunglasses | -
+-----------------------
+
+## Mini
+
+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/Jackal 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 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.
+
+**Neutral Mini:**
+- The cooldown is not effected, except for the Team Jackal/Sidekick.
+- If it gets thrown out of the ship, everything is fine except for the Jester.
+- If the Jester Mini gets voted out the game will end in a Jester win.
+
+**NOTE:**
+- If the Sheriff tries to kill the Mini before it's fully grown, nothing happens.
+- The Sheriff can kill the Impostor/Neutral Mini, but only if it's fully grown up.
+
+### Game Options
+| Name | Description |
+|----------|:-------------:|
+| Mini Spawn Chance | -
+| Mini | Mini Growing Up Duration
+-----------------------
+
+## VIP
+
+An Impostor, Jackal or Crewmate can be affected by the VIP (Very Important Player) Modifier.\
+The VIP will show everyone when he dies with a flash similar to the Seer Flash.\
+If the option Show Team Color is On, then everyone will get a flash in the color of the team the player was part of.
+
+Teams:
+- Impostor = Red
+- Neutral = Blue
+- Crewmate = White
+
+### Game Options
+| Name | Description
+|----------|:-------------:|
+| VIP Spawn Chance | -
+| VIP Quantity | -
+| Show Team Color | -
+-----------------------
+
+## Invert
+
+The Invert Modifier inverts your controls (no matter if keyboard or mouse).\
+The Invert can affect all teams (Impostor, Neutral, Crewmate).
+
+### Game Options
+| Name | Description
+|----------|:-------------:|
+| Invert Spawn Chance | -
+| Invert Quantity | -
+-----------------------
# Source code
It's bad I know, this is a side project and my second week of modding. So there are no best practices around here.
diff --git a/TheOtherRoles/Buttons.cs b/TheOtherRoles/Buttons.cs
index 73df41878..f17189cd4 100644
--- a/TheOtherRoles/Buttons.cs
+++ b/TheOtherRoles/Buttons.cs
@@ -14,22 +14,24 @@ static class HudManagerStartPatch
{
private static CustomButton engineerRepairButton;
private static CustomButton janitorCleanButton;
- private static CustomButton sheriffKillButton;
+ public static CustomButton sheriffKillButton;
private static CustomButton deputyHandcuffButton;
private static CustomButton timeMasterShieldButton;
private static CustomButton medicShieldButton;
private static CustomButton shifterShiftButton;
private static CustomButton morphlingButton;
private static CustomButton camouflagerButton;
+ private static CustomButton portalmakerPlacePortalButton;
+ private static CustomButton usePortalButton;
private static CustomButton hackerButton;
private static CustomButton hackerVitalsButton;
private static CustomButton hackerAdminTableButton;
private static CustomButton trackerTrackPlayerButton;
private static CustomButton trackerTrackCorpsesButton;
- private static CustomButton vampireKillButton;
+ public static CustomButton vampireKillButton;
private static CustomButton garlicButton;
- private static CustomButton jackalKillButton;
- private static CustomButton sidekickKillButton;
+ public static CustomButton jackalKillButton;
+ public static CustomButton sidekickKillButton;
private static CustomButton jackalSidekickButton;
private static CustomButton lighterButton;
private static CustomButton eraserButton;
@@ -44,6 +46,7 @@ static class HudManagerStartPatch
public static CustomButton mediumButton;
public static CustomButton pursuerButton;
public static CustomButton witchSpellButton;
+ public static CustomButton ninjaButton;
public static Dictionary> deputyHandcuffedButtons = null;
@@ -64,6 +67,8 @@ public static void setCustomButtonCooldowns() {
shifterShiftButton.MaxTimer = 0f;
morphlingButton.MaxTimer = Morphling.cooldown;
camouflagerButton.MaxTimer = Camouflager.cooldown;
+ portalmakerPlacePortalButton.MaxTimer = Portalmaker.cooldown;
+ usePortalButton.MaxTimer = Portalmaker.usePortalCooldown;
hackerButton.MaxTimer = Hacker.cooldown;
hackerVitalsButton.MaxTimer = Hacker.cooldown;
hackerAdminTableButton.MaxTimer = Hacker.cooldown;
@@ -86,7 +91,8 @@ public static void setCustomButtonCooldowns() {
mediumButton.MaxTimer = Medium.cooldown;
pursuerButton.MaxTimer = Pursuer.cooldown;
trackerTrackCorpsesButton.MaxTimer = Tracker.corpsesTrackingCooldown;
- witchSpellButton.MaxTimer = Witch.cooldown;
+ witchSpellButton.MaxTimer = Witch.cooldown;
+ ninjaButton.MaxTimer = Ninja.cooldown;
timeMasterShieldButton.EffectDuration = TimeMaster.shieldDuration;
hackerButton.EffectDuration = Hacker.duration;
@@ -365,6 +371,7 @@ public static void Postfix(HudManager __instance)
RPCProcedure.setFutureShielded(Medic.currentTarget.PlayerId);
else
RPCProcedure.medicSetShielded(Medic.currentTarget.PlayerId);
+ Medic.meetingAfterShielding = false;
},
() => { return Medic.medic != null && Medic.medic == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.Data.IsDead; },
() => { return !Medic.usedShield && Medic.currentTarget && PlayerControl.LocalPlayer.CanMove; },
@@ -713,7 +720,65 @@ public static void Postfix(HudManager __instance)
true
);
-
+ portalmakerPlacePortalButton = new CustomButton(
+ () => {
+ portalmakerPlacePortalButton.Timer = portalmakerPlacePortalButton.MaxTimer;
+
+ var pos = PlayerControl.LocalPlayer.transform.position;
+ byte[] buff = new byte[sizeof(float) * 2];
+ Buffer.BlockCopy(BitConverter.GetBytes(pos.x), 0, buff, 0 * sizeof(float), sizeof(float));
+ Buffer.BlockCopy(BitConverter.GetBytes(pos.y), 0, buff, 1 * sizeof(float), sizeof(float));
+
+ MessageWriter writer = AmongUsClient.Instance.StartRpc(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.PlacePortal, Hazel.SendOption.Reliable);
+ writer.WriteBytesAndSize(buff);
+ writer.EndMessage();
+ RPCProcedure.placePortal(buff);
+ },
+ () => { return Portalmaker.portalmaker != null && Portalmaker.portalmaker == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.Data.IsDead && Portal.secondPortal == null; },
+ () => { return PlayerControl.LocalPlayer.CanMove && Portal.secondPortal == null; },
+ () => { portalmakerPlacePortalButton.Timer = portalmakerPlacePortalButton.MaxTimer; },
+ Portalmaker.getPlacePortalButtonSprite(),
+ new Vector3(-1.8f, -0.06f, 0),
+ __instance,
+ KeyCode.F
+ );
+
+ usePortalButton = new CustomButton(
+ () => {
+ bool didTeleport = false;
+ Vector2 exit = Portal.findExit(PlayerControl.LocalPlayer.transform.position);
+ Vector2 entry = Portal.findEntry(PlayerControl.LocalPlayer.transform.position);
+ PlayerControl.LocalPlayer.NetTransform.RpcSnapTo(entry); // TODO: check for bans on servers
+
+ if (!PlayerControl.LocalPlayer.Data.IsDead) { // Ghosts can portal too, but non-blocking and only with a local animation
+ MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.UsePortal, Hazel.SendOption.Reliable, -1);
+ writer.Write((byte)PlayerControl.LocalPlayer.PlayerId);
+ AmongUsClient.Instance.FinishRpcImmediately(writer);
+ }
+ RPCProcedure.usePortal(PlayerControl.LocalPlayer.PlayerId);
+ usePortalButton.Timer = usePortalButton.MaxTimer;
+ HudManager.Instance.StartCoroutine(Effects.Lerp(Portal.teleportDuration, new Action((p) => { // Delayed action
+ PlayerControl.LocalPlayer.moveable = false;
+ PlayerControl.LocalPlayer.NetTransform.Halt();
+ if (p >= 0.5f && p <= 0.53f && !didTeleport) {
+ PlayerControl.LocalPlayer.NetTransform.RpcSnapTo(exit);
+ didTeleport = true;
+ }
+ if (p == 1f) {
+ PlayerControl.LocalPlayer.moveable = true;
+ }
+ })));
+ },
+ () => { return Portal.bothPlacedAndEnabled; },
+ () => { return PlayerControl.LocalPlayer.CanMove && Portal.locationNearEntry(PlayerControl.LocalPlayer.transform.position) && !Portal.isTeleporting; },
+ () => { usePortalButton.Timer = usePortalButton.MaxTimer; },
+ Portalmaker.getUsePortalButtonSprite(),
+ new Vector3(0.9f, -0.06f, 0),
+ __instance,
+ KeyCode.H,
+ mirror: true
+ );
+
// Jackal Sidekick Button
jackalSidekickButton = new CustomButton(
() => {
@@ -1288,10 +1353,14 @@ public static void Postfix(HudManager __instance)
RPCProcedure.setFutureSpelled(Witch.currentTarget.PlayerId);
}
if (attempt == MurderAttemptResult.BlankKill || attempt == MurderAttemptResult.PerformKill) {
- witchSpellButton.MaxTimer += Witch.cooldownAddition;
+ Witch.currentCooldownAddition += Witch.cooldownAddition;
+ witchSpellButton.MaxTimer = Witch.cooldown + Witch.currentCooldownAddition;
+ Patches.PlayerControlFixedUpdatePatch.miniCooldownUpdate(); // Modifies the MaxTimer if the witch is the mini
witchSpellButton.Timer = witchSpellButton.MaxTimer;
- if (Witch.triggerBothCooldowns)
- Witch.witch.killTimer = PlayerControl.GameOptions.KillCooldown;
+ if (Witch.triggerBothCooldowns) {
+ float multiplier = (Mini.mini != null && PlayerControl.LocalPlayer == Mini.mini) ? (Mini.isGrownUp() ? 0.66f : 2f) : 1f;
+ Witch.witch.killTimer = PlayerControl.GameOptions.KillCooldown * multiplier;
+ }
} else {
witchSpellButton.Timer = 0f;
}
@@ -1299,9 +1368,76 @@ public static void Postfix(HudManager __instance)
}
);
- // Set the default (or settings from the previous game) timers/durations when spawning the buttons
+ // Ninja mark and assassinate button
+ ninjaButton = new CustomButton(
+ () => {
+ if (Ninja.ninjaMarked != null) {
+ // Murder attempt with teleport
+ MurderAttemptResult attempt = Helpers.checkMuderAttempt(Ninja.ninja, Ninja.ninjaMarked);
+ if (attempt == MurderAttemptResult.PerformKill) {
+ // Create first trace before killing
+ var pos = PlayerControl.LocalPlayer.transform.position;
+ byte[] buff = new byte[sizeof(float) * 2];
+ Buffer.BlockCopy(BitConverter.GetBytes(pos.x), 0, buff, 0 * sizeof(float), sizeof(float));
+ Buffer.BlockCopy(BitConverter.GetBytes(pos.y), 0, buff, 1 * sizeof(float), sizeof(float));
+
+ MessageWriter writer = AmongUsClient.Instance.StartRpc(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.PlaceNinjaTrace, Hazel.SendOption.Reliable);
+ writer.WriteBytesAndSize(buff);
+ writer.EndMessage();
+ RPCProcedure.placeNinjaTrace(buff);
+
+ // Perform Kill
+ MessageWriter writer2 = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.UncheckedMurderPlayer, Hazel.SendOption.Reliable, -1);
+ writer2.Write(PlayerControl.LocalPlayer.PlayerId);
+ writer2.Write(Ninja.ninjaMarked.PlayerId);
+ writer2.Write(byte.MaxValue);
+ AmongUsClient.Instance.FinishRpcImmediately(writer2);
+ RPCProcedure.uncheckedMurderPlayer(PlayerControl.LocalPlayer.PlayerId, Ninja.ninjaMarked.PlayerId, byte.MaxValue);
+
+ // Create Second trace after killing
+ pos = Ninja.ninjaMarked.transform.position;
+ buff = new byte[sizeof(float) * 2];
+ Buffer.BlockCopy(BitConverter.GetBytes(pos.x), 0, buff, 0 * sizeof(float), sizeof(float));
+ Buffer.BlockCopy(BitConverter.GetBytes(pos.y), 0, buff, 1 * sizeof(float), sizeof(float));
+
+ MessageWriter writer3 = AmongUsClient.Instance.StartRpc(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.PlaceNinjaTrace, Hazel.SendOption.Reliable);
+ writer3.WriteBytesAndSize(buff);
+ writer3.EndMessage();
+ RPCProcedure.placeNinjaTrace(buff);
+ }
+
+ if (attempt == MurderAttemptResult.BlankKill || attempt == MurderAttemptResult.PerformKill) {
+ ninjaButton.Timer = ninjaButton.MaxTimer;
+ Ninja.ninja.killTimer = PlayerControl.GameOptions.KillCooldown;
+ } else if (attempt == MurderAttemptResult.SuppressKill) {
+ ninjaButton.Timer = 0f;
+ }
+ Ninja.ninjaMarked = null;
+ return;
+ }
+ if (Ninja.currentTarget != null) {
+ Ninja.ninjaMarked = Ninja.currentTarget;
+ ninjaButton.Timer = 5f;
+ }
+ },
+ () => { return Ninja.ninja != null && Ninja.ninja == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.Data.IsDead; },
+ () => { // CouldUse
+ ninjaButton.Sprite = Ninja.ninjaMarked != null ? Ninja.getKillButtonSprite() : Ninja.getMarkButtonSprite();
+ return (Ninja.currentTarget != null || Ninja.ninjaMarked != null) && PlayerControl.LocalPlayer.CanMove;
+ },
+ () => { // on meeting ends
+ ninjaButton.Timer = ninjaButton.MaxTimer;
+ Ninja.ninjaMarked = null;
+ },
+ Ninja.getMarkButtonSprite(),
+ new Vector3(-1.8f, -0.06f, 0),
+ __instance,
+ KeyCode.F
+ );
+
+ // Set the default (or settings from the previous game) timers / durations when spawning the buttons
setCustomButtonCooldowns();
deputyHandcuffedButtons = null;
}
}
-}
\ No newline at end of file
+}
diff --git a/TheOtherRoles/CustomOptionHolder.cs b/TheOtherRoles/CustomOptionHolder.cs
index 72aa25080..9bbf8ac95 100644
--- a/TheOtherRoles/CustomOptionHolder.cs
+++ b/TheOtherRoles/CustomOptionHolder.cs
@@ -8,10 +8,12 @@
using System.Reflection;
using System.Text;
using static TheOtherRoles.TheOtherRoles;
+using Types = TheOtherRoles.CustomOption.CustomOptionType;
namespace TheOtherRoles {
public class CustomOptionHolder {
public static string[] rates = new string[]{"0%", "10%", "20%", "30%", "40%", "50%", "60%", "70%", "80%", "90%", "100%"};
+ public static string[] ratesModifier = new string[]{"1", "2", "3"};
public static string[] presets = new string[]{"Preset 1", "Preset 2", "Preset 3", "Preset 4", "Preset 5"};
public static CustomOption presetSelection;
@@ -22,6 +24,8 @@ public class CustomOptionHolder {
public static CustomOption neutralRolesCountMax;
public static CustomOption impostorRolesCountMin;
public static CustomOption impostorRolesCountMax;
+ public static CustomOption modifiersCountMin;
+ public static CustomOption modifiersCountMax;
public static CustomOption mafiaSpawnRate;
public static CustomOption janitorCooldown;
@@ -42,16 +46,6 @@ public class CustomOptionHolder {
public static CustomOption eraserSpawnRate;
public static CustomOption eraserCooldown;
public static CustomOption eraserCanEraseAnyone;
-
- 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 loversEnableChat;
-
public static CustomOption guesserSpawnRate;
public static CustomOption guesserIsImpGuesserRate;
public static CustomOption guesserNumberOfShots;
@@ -97,10 +91,24 @@ public class CustomOptionHolder {
public static CustomOption witchTriggerBothCooldowns;
public static CustomOption witchVoteSavesTargets;
+ public static CustomOption ninjaSpawnRate;
+ public static CustomOption ninjaCooldown;
+ public static CustomOption ninjaKnowsTargetLocation;
+ public static CustomOption ninjaTraceTime;
+ public static CustomOption ninjaTraceColorTime;
+
public static CustomOption shifterSpawnRate;
public static CustomOption shifterShiftsModifiers;
public static CustomOption mayorSpawnRate;
+ public static CustomOption mayorCanSeeVoteColors;
+ public static CustomOption mayorTasksNeededToSeeVoteColors;
+
+ public static CustomOption portalmakerSpawnRate;
+ public static CustomOption portalmakerCooldown;
+ public static CustomOption portalmakerUsePortalCooldown;
+ public static CustomOption portalmakerLogOnlyColorType;
+ public static CustomOption portalmakerLogHasTime;
public static CustomOption engineerSpawnRate;
public static CustomOption engineerNumberOfFixes;
@@ -140,12 +148,15 @@ public class CustomOptionHolder {
public static CustomOption medicSpawnRate;
public static CustomOption medicShowShielded;
public static CustomOption medicShowAttemptToShielded;
- public static CustomOption medicSetShieldAfterMeeting;
+ public static CustomOption medicSetOrShowShieldAfterMeeting;
public static CustomOption medicShowAttemptToMedic;
+ public static CustomOption medicSetShieldAfterMeeting;
public static CustomOption swapperSpawnRate;
public static CustomOption swapperCanCallEmergency;
public static CustomOption swapperCanOnlySwapOthers;
+ public static CustomOption swapperSwapsNumber;
+ public static CustomOption swapperRechargeTasksNumber;
public static CustomOption seerSpawnRate;
public static CustomOption seerMode;
@@ -200,11 +211,6 @@ public class CustomOptionHolder {
public static CustomOption securityGuardCamRechargeTasksNumber;
public static CustomOption securityGuardNoMove;
- public static CustomOption baitSpawnRate;
- public static CustomOption baitHighlightAllVents;
- public static CustomOption baitReportDelay;
- public static CustomOption baitShowKillFlash;
-
public static CustomOption vultureSpawnRate;
public static CustomOption vultureCooldown;
public static CustomOption vultureNumberToWin;
@@ -217,7 +223,7 @@ public class CustomOptionHolder {
public static CustomOption mediumOneTimeUse;
public static CustomOption lawyerSpawnRate;
- public static CustomOption lawyerTargetKnows;
+ public static CustomOption lawyerTargetCanBeJester;
public static CustomOption lawyerWinsAfterMeetings;
public static CustomOption lawyerNeededMeetings;
public static CustomOption lawyerVision;
@@ -225,11 +231,47 @@ public class CustomOptionHolder {
public static CustomOption pursuerCooldown;
public static CustomOption pursuerBlanksNumber;
+ public static CustomOption modifierBait;
+ public static CustomOption modifierBaitQuantity;
+ public static CustomOption modifierBaitReportDelayMin;
+ public static CustomOption modifierBaitReportDelayMax;
+ public static CustomOption modifierBaitShowKillFlash;
+
+ public static CustomOption modifierLover;
+ public static CustomOption modifierLoverImpLoverRate;
+ public static CustomOption modifierLoverBothDie;
+ public static CustomOption modifierLoverEnableChat;
+
+ public static CustomOption modifierBloody;
+ public static CustomOption modifierBloodyQuantity;
+ public static CustomOption modifierBloodyDuration;
+
+ public static CustomOption modifierAntiTeleport;
+ public static CustomOption modifierAntiTeleportQuantity;
+
+ public static CustomOption modifierTieBreaker;
+
+ public static CustomOption modifierSunglasses;
+ public static CustomOption modifierSunglassesQuantity;
+ public static CustomOption modifierSunglassesVision;
+
+ public static CustomOption modifierMini;
+ public static CustomOption modifierMiniGrowingUpDuration;
+
+ public static CustomOption modifierVip;
+ public static CustomOption modifierVipQuantity;
+ public static CustomOption modifierVipShowColor;
+
+ public static CustomOption modifierInvert;
+ public static CustomOption modifierInvertQuantity;
+ public static CustomOption modifierInvertDuration;
+
public static CustomOption maxNumberOfMeetings;
public static CustomOption blockSkippingInEmergencyMeetings;
public static CustomOption noVoteIsSelfVote;
public static CustomOption hidePlayerNames;
public static CustomOption allowParallelMedBayScans;
+ public static CustomOption shieldFirstKill;
public static CustomOption dynamicMap;
public static CustomOption dynamicMapEnableSkeld;
@@ -251,231 +293,275 @@ private static byte ToByte(float f) {
public static void Load() {
+
// Role Options
- presetSelection = CustomOption.Create(0, cs(new Color(204f / 255f, 204f / 255f, 0, 1f), "Preset"), presets, null, true);
- activateRoles = CustomOption.Create(1, cs(new Color(204f / 255f, 204f / 255f, 0, 1f), "Enable Mod Roles And Block Vanilla Roles"), true, null, true);
+ presetSelection = CustomOption.Create(0, Types.General, cs(new Color(204f / 255f, 204f / 255f, 0, 1f), "Preset"), presets, null, true);
+ activateRoles = CustomOption.Create(1, Types.General, cs(new Color(204f / 255f, 204f / 255f, 0, 1f), "Enable Mod Roles And Block Vanilla Roles"), true, null, true);
// Using new id's for the options to not break compatibilty with older versions
- crewmateRolesCountMin = CustomOption.Create(300, cs(new Color(204f / 255f, 204f / 255f, 0, 1f), "Minimum Crewmate Roles"), 0f, 0f, 15f, 1f, null, true);
- crewmateRolesCountMax = CustomOption.Create(301, cs(new Color(204f / 255f, 204f / 255f, 0, 1f), "Maximum Crewmate Roles"), 0f, 0f, 15f, 1f);
- neutralRolesCountMin = CustomOption.Create(302, cs(new Color(204f / 255f, 204f / 255f, 0, 1f), "Minimum Neutral Roles"), 0f, 0f, 15f, 1f);
- neutralRolesCountMax = CustomOption.Create(303, cs(new Color(204f / 255f, 204f / 255f, 0, 1f), "Maximum Neutral Roles"), 0f, 0f, 15f, 1f);
- impostorRolesCountMin = CustomOption.Create(304, cs(new Color(204f / 255f, 204f / 255f, 0, 1f), "Minimum Impostor Roles"), 0f, 0f, 3f, 1f);
- impostorRolesCountMax = CustomOption.Create(305, cs(new Color(204f / 255f, 204f / 255f, 0, 1f), "Maximum Impostor Roles"), 0f, 0f, 3f, 1f);
-
- mafiaSpawnRate = CustomOption.Create(10, cs(Janitor.color, "Mafia"), rates, null, true);
- janitorCooldown = CustomOption.Create(11, "Janitor Cooldown", 30f, 10f, 60f, 2.5f, mafiaSpawnRate);
-
- morphlingSpawnRate = CustomOption.Create(20, cs(Morphling.color, "Morphling"), rates, null, true);
- morphlingCooldown = CustomOption.Create(21, "Morphling Cooldown", 30f, 10f, 60f, 2.5f, morphlingSpawnRate);
- morphlingDuration = CustomOption.Create(22, "Morph Duration", 10f, 1f, 20f, 0.5f, morphlingSpawnRate);
-
- camouflagerSpawnRate = CustomOption.Create(30, cs(Camouflager.color, "Camouflager"), rates, null, true);
- camouflagerCooldown = CustomOption.Create(31, "Camouflager Cooldown", 30f, 10f, 60f, 2.5f, camouflagerSpawnRate);
- camouflagerDuration = CustomOption.Create(32, "Camo Duration", 10f, 1f, 20f, 0.5f, camouflagerSpawnRate);
-
- vampireSpawnRate = CustomOption.Create(40, cs(Vampire.color, "Vampire"), rates, null, true);
- vampireKillDelay = CustomOption.Create(41, "Vampire Kill Delay", 10f, 1f, 20f, 1f, vampireSpawnRate);
- vampireCooldown = CustomOption.Create(42, "Vampire Cooldown", 30f, 10f, 60f, 2.5f, vampireSpawnRate);
- vampireCanKillNearGarlics = CustomOption.Create(43, "Vampire Can Kill Near Garlics", true, vampireSpawnRate);
-
- eraserSpawnRate = CustomOption.Create(230, cs(Eraser.color, "Eraser"), rates, null, true);
- eraserCooldown = CustomOption.Create(231, "Eraser Cooldown", 30f, 10f, 120f, 5f, eraserSpawnRate);
- eraserCanEraseAnyone = CustomOption.Create(232, "Eraser Can Erase Anyone", false, eraserSpawnRate);
-
- tricksterSpawnRate = CustomOption.Create(250, cs(Trickster.color, "Trickster"), rates, null, true);
- tricksterPlaceBoxCooldown = CustomOption.Create(251, "Trickster Box Cooldown", 10f, 2.5f, 30f, 2.5f, tricksterSpawnRate);
- tricksterLightsOutCooldown = CustomOption.Create(252, "Trickster Lights Out Cooldown", 30f, 10f, 60f, 5f, tricksterSpawnRate);
- tricksterLightsOutDuration = CustomOption.Create(253, "Trickster Lights Out Duration", 15f, 5f, 60f, 2.5f, tricksterSpawnRate);
-
- cleanerSpawnRate = CustomOption.Create(260, cs(Cleaner.color, "Cleaner"), rates, null, true);
- cleanerCooldown = CustomOption.Create(261, "Cleaner Cooldown", 30f, 10f, 60f, 2.5f, cleanerSpawnRate);
-
- warlockSpawnRate = CustomOption.Create(270, cs(Cleaner.color, "Warlock"), rates, null, true);
- warlockCooldown = CustomOption.Create(271, "Warlock Cooldown", 30f, 10f, 60f, 2.5f, warlockSpawnRate);
- warlockRootTime = CustomOption.Create(272, "Warlock Root Time", 5f, 0f, 15f, 1f, warlockSpawnRate);
-
- bountyHunterSpawnRate = CustomOption.Create(320, cs(BountyHunter.color, "Bounty Hunter"), rates, null, true);
- bountyHunterBountyDuration = CustomOption.Create(321, "Duration After Which Bounty Changes", 60f, 10f, 180f, 10f, bountyHunterSpawnRate);
- bountyHunterReducedCooldown = CustomOption.Create(322, "Cooldown After Killing Bounty", 2.5f, 0f, 30f, 2.5f, bountyHunterSpawnRate);
- bountyHunterPunishmentTime = CustomOption.Create(323, "Additional Cooldown After Killing Others", 20f, 0f, 60f, 2.5f, bountyHunterSpawnRate);
- bountyHunterShowArrow = CustomOption.Create(324, "Show Arrow Pointing Towards The Bounty", true, bountyHunterSpawnRate);
- bountyHunterArrowUpdateIntervall = CustomOption.Create(325, "Arrow Update Intervall", 15f, 2.5f, 60f, 2.5f, bountyHunterShowArrow);
-
- witchSpawnRate = CustomOption.Create(370, cs(Witch.color, "Witch"), rates, null, true);
- witchCooldown = CustomOption.Create(371, "Witch Spell Casting Cooldown", 30f, 10f, 120f, 5f, witchSpawnRate);
- witchAdditionalCooldown = CustomOption.Create(372, "Witch Additional Cooldown", 10f, 0f, 60f, 5f, witchSpawnRate);
- witchCanSpellAnyone = CustomOption.Create(373, "Witch Can Spell Anyone", false, witchSpawnRate);
- witchSpellCastingDuration = CustomOption.Create(374, "Spell Casting Duration", 1f, 0f, 10f, 1f, witchSpawnRate);
- witchTriggerBothCooldowns = CustomOption.Create(375, "Trigger Both Cooldowns", true, witchSpawnRate);
- witchVoteSavesTargets = CustomOption.Create(376, "Voting The Witch Saves All The Targets", true, witchSpawnRate);
-
- 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);
- loversEnableChat = CustomOption.Create(54, "Enable Lover Chat", 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);
- guesserHasMultipleShotsPerMeeting = CustomOption.Create(313, "Guesser Can Shoot Multiple Times Per Meeting", false, guesserSpawnRate);
- guesserShowInfoInGhostChat = CustomOption.Create(314, "Guesses Visible In Ghost Chat", true, guesserSpawnRate);
- guesserKillsThroughShield = CustomOption.Create(315, "Guesses Ignore The Medic Shield", true, guesserSpawnRate);
- guesserEvilCanKillSpy = CustomOption.Create(316, "Evil Guesser Can Guess The Spy", true, guesserSpawnRate);
- guesserSpawnBothRate = CustomOption.Create(317, "Both Guesser Spawn Rate", rates, guesserSpawnRate);
- guesserCantGuessSnitchIfTaksDone = CustomOption.Create(318, "Guesser Can't Guess Snitch When Tasks Completed", true, guesserSpawnRate);
-
- jesterSpawnRate = CustomOption.Create(60, cs(Jester.color, "Jester"), rates, null, true);
- jesterCanCallEmergency = CustomOption.Create(61, "Jester Can Call Emergency Meeting", true, jesterSpawnRate);
- jesterHasImpostorVision = CustomOption.Create(62, "Jester Has Impostor Vision", false, jesterSpawnRate);
-
- arsonistSpawnRate = CustomOption.Create(290, cs(Arsonist.color, "Arsonist"), rates, null, true);
- arsonistCooldown = CustomOption.Create(291, "Arsonist Cooldown", 12.5f, 2.5f, 60f, 2.5f, arsonistSpawnRate);
- arsonistDuration = CustomOption.Create(292, "Arsonist Douse Duration", 3f, 1f, 10f, 1f, arsonistSpawnRate);
-
- jackalSpawnRate = CustomOption.Create(220, cs(Jackal.color, "Jackal"), rates, null, true);
- jackalKillCooldown = CustomOption.Create(221, "Jackal/Sidekick Kill Cooldown", 30f, 10f, 60f, 2.5f, jackalSpawnRate);
- jackalCreateSidekickCooldown = CustomOption.Create(222, "Jackal Create Sidekick Cooldown", 30f, 10f, 60f, 2.5f, jackalSpawnRate);
- jackalCanUseVents = CustomOption.Create(223, "Jackal Can Use Vents", true, jackalSpawnRate);
- jackalCanCreateSidekick = CustomOption.Create(224, "Jackal Can Create A Sidekick", false, jackalSpawnRate);
- sidekickPromotesToJackal = CustomOption.Create(225, "Sidekick Gets Promoted To Jackal On Jackal Death", false, jackalSpawnRate);
- sidekickCanKill = CustomOption.Create(226, "Sidekick Can Kill", false, jackalSpawnRate);
- sidekickCanUseVents = CustomOption.Create(227, "Sidekick Can Use Vents", true, jackalSpawnRate);
- jackalPromotedFromSidekickCanCreateSidekick = CustomOption.Create(228, "Jackals Promoted From Sidekick Can Create A Sidekick", true, jackalSpawnRate);
- jackalCanCreateSidekickFromImpostor = CustomOption.Create(229, "Jackals Can Make An Impostor To His Sidekick", true, jackalSpawnRate);
- jackalAndSidekickHaveImpostorVision = CustomOption.Create(430, "Jackal And Sidekick Have Impostor Vision", false, jackalSpawnRate);
-
- vultureSpawnRate = CustomOption.Create(340, cs(Vulture.color, "Vulture"), rates, null, true);
- vultureCooldown = CustomOption.Create(341, "Vulture Cooldown", 15f, 10f, 60f, 2.5f, vultureSpawnRate);
- vultureNumberToWin = CustomOption.Create(342, "Number Of Corpses Needed To Be Eaten", 4f, 1f, 10f, 1f, vultureSpawnRate);
- vultureCanUseVents = CustomOption.Create(343, "Vulture Can Use Vents", true, vultureSpawnRate);
- vultureShowArrows = CustomOption.Create(344, "Show Arrows Pointing Towards The Corpses", true, vultureSpawnRate);
-
- lawyerSpawnRate = CustomOption.Create(350, cs(Lawyer.color, "Lawyer"), rates, null, true);
- lawyerTargetKnows = CustomOption.Create(351, "Lawyer Target Knows", true, lawyerSpawnRate);
- lawyerWinsAfterMeetings = CustomOption.Create(352, "Lawyer Wins After Meetings", false, lawyerSpawnRate);
- lawyerNeededMeetings = CustomOption.Create(353, "Lawyer Needed Meetings To Win", 5f, 1f, 15f, 1f, lawyerWinsAfterMeetings);
- lawyerVision = CustomOption.Create(354, "Lawyer Vision", 1f, 0.25f, 3f, 0.25f, lawyerSpawnRate);
- lawyerKnowsRole = CustomOption.Create(355, "Lawyer Knows Target Role", false, lawyerSpawnRate);
- pursuerCooldown = CustomOption.Create(356, "Pursuer Blank Cooldown", 30f, 5f, 60f, 2.5f, lawyerSpawnRate);
- pursuerBlanksNumber = CustomOption.Create(357, "Pursuer Number Of Blanks", 5f, 1f, 20f, 1f, lawyerSpawnRate);
-
- shifterSpawnRate = CustomOption.Create(70, cs(Shifter.color, "Shifter"), rates, null, true);
- shifterShiftsModifiers = CustomOption.Create(71, "Shifter Shifts Modifiers", false, shifterSpawnRate);
-
- mayorSpawnRate = CustomOption.Create(80, cs(Mayor.color, "Mayor"), rates, null, true);
-
- engineerSpawnRate = CustomOption.Create(90, cs(Engineer.color, "Engineer"), rates, null, true);
- engineerNumberOfFixes = CustomOption.Create(91, "Number Of Sabotage Fixes", 1f, 1f, 3f, 1f, engineerSpawnRate);
- engineerHighlightForImpostors = CustomOption.Create(92, "Impostors See Vents Highlighted", true, engineerSpawnRate);
- engineerHighlightForTeamJackal = CustomOption.Create(93, "Jackal and Sidekick See Vents Highlighted ", true, engineerSpawnRate);
-
- sheriffSpawnRate = CustomOption.Create(100, cs(Sheriff.color, "Sheriff"), rates, null, true);
- sheriffCooldown = CustomOption.Create(101, "Sheriff Cooldown", 30f, 10f, 60f, 2.5f, sheriffSpawnRate);
- sheriffCanKillNeutrals = CustomOption.Create(102, "Sheriff Can Kill Neutrals", false, sheriffSpawnRate);
- deputySpawnRate = CustomOption.Create(103, "Sheriff Has A Deputy", rates, sheriffSpawnRate);
- deputyNumberOfHandcuffs = CustomOption.Create(104, "Deputy Number Of Handcuffs", 3f, 1f, 10f, 1f, deputySpawnRate);
- deputyHandcuffCooldown = CustomOption.Create(105, "Handcuff Cooldown", 30f, 10f, 60f, 2.5f, deputySpawnRate);
- deputyHandcuffDuration = CustomOption.Create(106, "Handcuff Duration", 15f, 5f, 60f, 2.5f, deputySpawnRate);
- deputyKnowsSheriff = CustomOption.Create(107, "Sheriff And Deputy Know Each Other ", true, deputySpawnRate);
- deputyGetsPromoted = CustomOption.Create(108, "Deputy Gets Promoted To Sheriff", new string[] { "Off", "On (Immediately)", "On (After Meeting)" }, deputySpawnRate);
- deputyKeepsHandcuffs = CustomOption.Create(109, "Deputy Keeps Handcuffs When Promoted", true, deputyGetsPromoted);
-
- lighterSpawnRate = CustomOption.Create(110, cs(Lighter.color, "Lighter"), rates, null, true);
- lighterModeLightsOnVision = CustomOption.Create(111, "Lighter Mode Vision On Lights On", 2f, 0.25f, 5f, 0.25f, lighterSpawnRate);
- lighterModeLightsOffVision = CustomOption.Create(112, "Lighter Mode Vision On Lights Off", 0.75f, 0.25f, 5f, 0.25f, lighterSpawnRate);
- lighterCooldown = CustomOption.Create(113, "Lighter Cooldown", 30f, 5f, 120f, 5f, lighterSpawnRate);
- lighterDuration = CustomOption.Create(114, "Lighter Duration", 5f, 2.5f, 60f, 2.5f, lighterSpawnRate);
-
- detectiveSpawnRate = CustomOption.Create(120, cs(Detective.color, "Detective"), rates, null, true);
- detectiveAnonymousFootprints = CustomOption.Create(121, "Anonymous Footprints", false, detectiveSpawnRate);
- detectiveFootprintIntervall = CustomOption.Create(122, "Footprint Intervall", 0.5f, 0.25f, 10f, 0.25f, detectiveSpawnRate);
- detectiveFootprintDuration = CustomOption.Create(123, "Footprint Duration", 5f, 0.25f, 10f, 0.25f, detectiveSpawnRate);
- detectiveReportNameDuration = CustomOption.Create(124, "Time Where Detective Reports Will Have Name", 0, 0, 60, 2.5f, detectiveSpawnRate);
- detectiveReportColorDuration = CustomOption.Create(125, "Time Where Detective Reports Will Have Color Type", 20, 0, 120, 2.5f, detectiveSpawnRate);
-
- timeMasterSpawnRate = CustomOption.Create(130, cs(TimeMaster.color, "Time Master"), rates, null, true);
- timeMasterCooldown = CustomOption.Create(131, "Time Master Cooldown", 30f, 10f, 120f, 2.5f, timeMasterSpawnRate);
- timeMasterRewindTime = CustomOption.Create(132, "Rewind Time", 3f, 1f, 10f, 1f, timeMasterSpawnRate);
- timeMasterShieldDuration = CustomOption.Create(133, "Time Master Shield Duration", 3f, 1f, 20f, 1f, timeMasterSpawnRate);
-
- medicSpawnRate = CustomOption.Create(140, cs(Medic.color, "Medic"), rates, null, true);
- medicShowShielded = CustomOption.Create(143, "Show Shielded Player", new string[] {"Everyone", "Shielded + Medic", "Medic"}, medicSpawnRate);
- medicShowAttemptToShielded = CustomOption.Create(144, "Shielded Player Sees Murder Attempt", false, medicSpawnRate);
- medicSetShieldAfterMeeting = CustomOption.Create(145, "Shield Will Be Set After The Next Meeting", false, medicSpawnRate);
- medicShowAttemptToMedic = CustomOption.Create(146, "Medic Sees Murder Attempt On Shielded Player", false, medicSpawnRate);
-
- swapperSpawnRate = CustomOption.Create(150, cs(Swapper.color, "Swapper"), rates, null, true);
- swapperCanCallEmergency = CustomOption.Create(151, "Swapper can call emergency meeting", false, swapperSpawnRate);
- swapperCanOnlySwapOthers = CustomOption.Create(152, "Swapper can only swap others", false, swapperSpawnRate);
-
- seerSpawnRate = CustomOption.Create(160, cs(Seer.color, "Seer"), rates, null, true);
- seerMode = CustomOption.Create(161, "Seer Mode", new string[]{ "Show Death Flash + Souls", "Show Death Flash", "Show Souls"}, seerSpawnRate);
- seerLimitSoulDuration = CustomOption.Create(163, "Seer Limit Soul Duration", false, seerSpawnRate);
- seerSoulDuration = CustomOption.Create(162, "Seer Soul Duration", 15f, 0f, 120f, 5f, seerLimitSoulDuration);
+ crewmateRolesCountMin = CustomOption.Create(300, Types.General, cs(new Color(204f / 255f, 204f / 255f, 0, 1f), "Minimum Crewmate Roles"), 0f, 0f, 15f, 1f, null, true);
+ crewmateRolesCountMax = CustomOption.Create(301, Types.General, cs(new Color(204f / 255f, 204f / 255f, 0, 1f), "Maximum Crewmate Roles"), 0f, 0f, 15f, 1f);
+ neutralRolesCountMin = CustomOption.Create(302, Types.General, cs(new Color(204f / 255f, 204f / 255f, 0, 1f), "Minimum Neutral Roles"), 0f, 0f, 15f, 1f);
+ neutralRolesCountMax = CustomOption.Create(303, Types.General, cs(new Color(204f / 255f, 204f / 255f, 0, 1f), "Maximum Neutral Roles"), 0f, 0f, 15f, 1f);
+ impostorRolesCountMin = CustomOption.Create(304, Types.General, cs(new Color(204f / 255f, 204f / 255f, 0, 1f), "Minimum Impostor Roles"), 0f, 0f, 3f, 1f);
+ impostorRolesCountMax = CustomOption.Create(305, Types.General, cs(new Color(204f / 255f, 204f / 255f, 0, 1f), "Maximum Impostor Roles"), 0f, 0f, 3f, 1f);
+ modifiersCountMin = CustomOption.Create(306, Types.General, cs(new Color(204f / 255f, 204f / 255f, 0, 1f), "Minimum Modifiers"), 0f, 0f, 15f, 1f);
+ modifiersCountMax = CustomOption.Create(307, Types.General, cs(new Color(204f / 255f, 204f / 255f, 0, 1f), "Maximum Modifiers"), 0f, 0f, 15f, 1f);
+
+ mafiaSpawnRate = CustomOption.Create(10, Types.Impostor, cs(Janitor.color, "Mafia"), rates, null, true);
+ janitorCooldown = CustomOption.Create(11, Types.Impostor, "Janitor Cooldown", 30f, 10f, 60f, 2.5f, mafiaSpawnRate);
+
+ morphlingSpawnRate = CustomOption.Create(20, Types.Impostor, cs(Morphling.color, "Morphling"), rates, null, true);
+ morphlingCooldown = CustomOption.Create(21, Types.Impostor, "Morphling Cooldown", 30f, 10f, 60f, 2.5f, morphlingSpawnRate);
+ morphlingDuration = CustomOption.Create(22, Types.Impostor, "Morph Duration", 10f, 1f, 20f, 0.5f, morphlingSpawnRate);
+
+ camouflagerSpawnRate = CustomOption.Create(30, Types.Impostor, cs(Camouflager.color, "Camouflager"), rates, null, true);
+ camouflagerCooldown = CustomOption.Create(31, Types.Impostor, "Camouflager Cooldown", 30f, 10f, 60f, 2.5f, camouflagerSpawnRate);
+ camouflagerDuration = CustomOption.Create(32, Types.Impostor, "Camo Duration", 10f, 1f, 20f, 0.5f, camouflagerSpawnRate);
+
+ vampireSpawnRate = CustomOption.Create(40, Types.Impostor, cs(Vampire.color, "Vampire"), rates, null, true);
+ vampireKillDelay = CustomOption.Create(41, Types.Impostor, "Vampire Kill Delay", 10f, 1f, 20f, 1f, vampireSpawnRate);
+ vampireCooldown = CustomOption.Create(42, Types.Impostor, "Vampire Cooldown", 30f, 10f, 60f, 2.5f, vampireSpawnRate);
+ vampireCanKillNearGarlics = CustomOption.Create(43, Types.Impostor, "Vampire Can Kill Near Garlics", true, vampireSpawnRate);
+
+ eraserSpawnRate = CustomOption.Create(230, Types.Impostor, cs(Eraser.color, "Eraser"), rates, null, true);
+ eraserCooldown = CustomOption.Create(231, Types.Impostor, "Eraser Cooldown", 30f, 10f, 120f, 5f, eraserSpawnRate);
+ eraserCanEraseAnyone = CustomOption.Create(232, Types.Impostor, "Eraser Can Erase Anyone", false, eraserSpawnRate);
+
+ tricksterSpawnRate = CustomOption.Create(250, Types.Impostor, cs(Trickster.color, "Trickster"), rates, null, true);
+ tricksterPlaceBoxCooldown = CustomOption.Create(251, Types.Impostor, "Trickster Box Cooldown", 10f, 2.5f, 30f, 2.5f, tricksterSpawnRate);
+ tricksterLightsOutCooldown = CustomOption.Create(252, Types.Impostor, "Trickster Lights Out Cooldown", 30f, 10f, 60f, 5f, tricksterSpawnRate);
+ tricksterLightsOutDuration = CustomOption.Create(253, Types.Impostor, "Trickster Lights Out Duration", 15f, 5f, 60f, 2.5f, tricksterSpawnRate);
+
+ cleanerSpawnRate = CustomOption.Create(260, Types.Impostor, cs(Cleaner.color, "Cleaner"), rates, null, true);
+ cleanerCooldown = CustomOption.Create(261, Types.Impostor, "Cleaner Cooldown", 30f, 10f, 60f, 2.5f, cleanerSpawnRate);
+
+ warlockSpawnRate = CustomOption.Create(270, Types.Impostor, cs(Cleaner.color, "Warlock"), rates, null, true);
+ warlockCooldown = CustomOption.Create(271, Types.Impostor, "Warlock Cooldown", 30f, 10f, 60f, 2.5f, warlockSpawnRate);
+ warlockRootTime = CustomOption.Create(272, Types.Impostor, "Warlock Root Time", 5f, 0f, 15f, 1f, warlockSpawnRate);
+
+ bountyHunterSpawnRate = CustomOption.Create(320, Types.Impostor, cs(BountyHunter.color, "Bounty Hunter"), rates, null, true);
+ bountyHunterBountyDuration = CustomOption.Create(321, Types.Impostor, "Duration After Which Bounty Changes", 60f, 10f, 180f, 10f, bountyHunterSpawnRate);
+ bountyHunterReducedCooldown = CustomOption.Create(322, Types.Impostor, "Cooldown After Killing Bounty", 2.5f, 0f, 30f, 2.5f, bountyHunterSpawnRate);
+ bountyHunterPunishmentTime = CustomOption.Create(323, Types.Impostor, "Additional Cooldown After Killing Others", 20f, 0f, 60f, 2.5f, bountyHunterSpawnRate);
+ bountyHunterShowArrow = CustomOption.Create(324, Types.Impostor, "Show Arrow Pointing Towards The Bounty", true, bountyHunterSpawnRate);
+ bountyHunterArrowUpdateIntervall = CustomOption.Create(325, Types.Impostor, "Arrow Update Intervall", 15f, 2.5f, 60f, 2.5f, bountyHunterShowArrow);
+
+ witchSpawnRate = CustomOption.Create(370, Types.Impostor, cs(Witch.color, "Witch"), rates, null, true);
+ witchCooldown = CustomOption.Create(371, Types.Impostor, "Witch Spell Casting Cooldown", 30f, 10f, 120f, 5f, witchSpawnRate);
+ witchAdditionalCooldown = CustomOption.Create(372, Types.Impostor, "Witch Additional Cooldown", 10f, 0f, 60f, 5f, witchSpawnRate);
+ witchCanSpellAnyone = CustomOption.Create(373, Types.Impostor, "Witch Can Spell Anyone", false, witchSpawnRate);
+ witchSpellCastingDuration = CustomOption.Create(374, Types.Impostor, "Spell Casting Duration", 1f, 0f, 10f, 1f, witchSpawnRate);
+ witchTriggerBothCooldowns = CustomOption.Create(375, Types.Impostor, "Trigger Both Cooldowns", true, witchSpawnRate);
+ witchVoteSavesTargets = CustomOption.Create(376, Types.Impostor, "Voting The Witch Saves All The Targets", true, witchSpawnRate);
+
+ ninjaSpawnRate = CustomOption.Create(380, Types.Impostor, cs(Ninja.color, "Ninja"), rates, null, true);
+ ninjaCooldown = CustomOption.Create(381, Types.Impostor, "Ninja Mark Cooldown", 30f, 10f, 120f, 5f, ninjaSpawnRate);
+ ninjaKnowsTargetLocation = CustomOption.Create(382, Types.Impostor, "Ninja Knows Location Of Target", true, ninjaSpawnRate);
+ ninjaTraceTime = CustomOption.Create(383, Types.Impostor, "Trace Duration", 5f, 1f, 20f, 0.5f, ninjaSpawnRate);
+ ninjaTraceColorTime = CustomOption.Create(384, Types.Impostor, "Time Till Trace Color Has Faded", 2f, 0f, 20f, 0.5f, ninjaSpawnRate);
+ guesserSpawnRate = CustomOption.Create(310, Types.Neutral, cs(Guesser.color, "Guesser"), rates, null, true);
+ guesserIsImpGuesserRate = CustomOption.Create(311, Types.Neutral, "Chance That The Guesser Is An Impostor", rates, guesserSpawnRate);
+ guesserNumberOfShots = CustomOption.Create(312, Types.Neutral, "Guesser Number Of Shots", 2f, 1f, 15f, 1f, guesserSpawnRate);
+ guesserHasMultipleShotsPerMeeting = CustomOption.Create(313, Types.Neutral, "Guesser Can Shoot Multiple Times Per Meeting", false, guesserSpawnRate);
+ guesserShowInfoInGhostChat = CustomOption.Create(314, Types.Neutral, "Guesses Visible In Ghost Chat", true, guesserSpawnRate);
+ guesserKillsThroughShield = CustomOption.Create(315, Types.Neutral, "Guesses Ignore The Medic Shield", true, guesserSpawnRate);
+ guesserEvilCanKillSpy = CustomOption.Create(316, Types.Neutral, "Evil Guesser Can Guess The Spy", true, guesserSpawnRate);
+ guesserSpawnBothRate = CustomOption.Create(317, Types.Neutral, "Both Guesser Spawn Rate", rates, guesserSpawnRate);
+ guesserCantGuessSnitchIfTaksDone = CustomOption.Create(318, Types.Neutral, "Guesser Can't Guess Snitch When Tasks Completed", true, guesserSpawnRate);
+
+ jesterSpawnRate = CustomOption.Create(60, Types.Neutral, cs(Jester.color, "Jester"), rates, null, true);
+ jesterCanCallEmergency = CustomOption.Create(61, Types.Neutral, "Jester Can Call Emergency Meeting", true, jesterSpawnRate);
+ jesterHasImpostorVision = CustomOption.Create(62, Types.Neutral, "Jester Has Impostor Vision", false, jesterSpawnRate);
+
+ arsonistSpawnRate = CustomOption.Create(290, Types.Neutral, cs(Arsonist.color, "Arsonist"), rates, null, true);
+ arsonistCooldown = CustomOption.Create(291, Types.Neutral, "Arsonist Cooldown", 12.5f, 2.5f, 60f, 2.5f, arsonistSpawnRate);
+ arsonistDuration = CustomOption.Create(292, Types.Neutral, "Arsonist Douse Duration", 3f, 1f, 10f, 1f, arsonistSpawnRate);
+
+ jackalSpawnRate = CustomOption.Create(220, Types.Neutral, cs(Jackal.color, "Jackal"), rates, null, true);
+ jackalKillCooldown = CustomOption.Create(221, Types.Neutral, "Jackal/Sidekick Kill Cooldown", 30f, 10f, 60f, 2.5f, jackalSpawnRate);
+ jackalCreateSidekickCooldown = CustomOption.Create(222, Types.Neutral, "Jackal Create Sidekick Cooldown", 30f, 10f, 60f, 2.5f, jackalSpawnRate);
+ jackalCanUseVents = CustomOption.Create(223, Types.Neutral, "Jackal Can Use Vents", true, jackalSpawnRate);
+ jackalCanCreateSidekick = CustomOption.Create(224, Types.Neutral, "Jackal Can Create A Sidekick", false, jackalSpawnRate);
+ sidekickPromotesToJackal = CustomOption.Create(225, Types.Neutral, "Sidekick Gets Promoted To Jackal On Jackal Death", false, jackalCanCreateSidekick);
+ sidekickCanKill = CustomOption.Create(226, Types.Neutral, "Sidekick Can Kill", false, jackalCanCreateSidekick);
+ sidekickCanUseVents = CustomOption.Create(227, Types.Neutral, "Sidekick Can Use Vents", true, jackalCanCreateSidekick);
+ jackalPromotedFromSidekickCanCreateSidekick = CustomOption.Create(228, Types.Neutral, "Jackals Promoted From Sidekick Can Create A Sidekick", true, sidekickPromotesToJackal);
+ jackalCanCreateSidekickFromImpostor = CustomOption.Create(229, Types.Neutral, "Jackals Can Make An Impostor To His Sidekick", true, jackalCanCreateSidekick);
+ jackalAndSidekickHaveImpostorVision = CustomOption.Create(430, Types.Neutral, "Jackal And Sidekick Have Impostor Vision", false, jackalSpawnRate);
+
+ vultureSpawnRate = CustomOption.Create(340, Types.Neutral, cs(Vulture.color, "Vulture"), rates, null, true);
+ vultureCooldown = CustomOption.Create(341, Types.Neutral, "Vulture Cooldown", 15f, 10f, 60f, 2.5f, vultureSpawnRate);
+ vultureNumberToWin = CustomOption.Create(342, Types.Neutral, "Number Of Corpses Needed To Be Eaten", 4f, 1f, 10f, 1f, vultureSpawnRate);
+ vultureCanUseVents = CustomOption.Create(343, Types.Neutral, "Vulture Can Use Vents", true, vultureSpawnRate);
+ vultureShowArrows = CustomOption.Create(344, Types.Neutral, "Show Arrows Pointing Towards The Corpses", true, vultureSpawnRate);
+
+ lawyerSpawnRate = CustomOption.Create(350, Types.Neutral, cs(Lawyer.color, "Lawyer"), rates, null, true);
+ lawyerTargetCanBeJester = CustomOption.Create(351, Types.Neutral, "Lawyer Target Can Be The Jester", false, lawyerSpawnRate);
+ lawyerWinsAfterMeetings = CustomOption.Create(352, Types.Neutral, "Lawyer Wins After Meetings", false, lawyerSpawnRate);
+ lawyerNeededMeetings = CustomOption.Create(353, Types.Neutral, "Lawyer Needed Meetings To Win", 5f, 1f, 15f, 1f, lawyerWinsAfterMeetings);
+ lawyerVision = CustomOption.Create(354, Types.Neutral, "Lawyer Vision", 1f, 0.25f, 3f, 0.25f, lawyerSpawnRate);
+ lawyerKnowsRole = CustomOption.Create(355, Types.Neutral, "Lawyer Knows Target Role", false, lawyerSpawnRate);
+ pursuerCooldown = CustomOption.Create(356, Types.Neutral, "Pursuer Blank Cooldown", 30f, 5f, 60f, 2.5f, lawyerSpawnRate);
+ pursuerBlanksNumber = CustomOption.Create(357, Types.Neutral, "Pursuer Number Of Blanks", 5f, 1f, 20f, 1f, lawyerSpawnRate);
+
+ shifterSpawnRate = CustomOption.Create(70, Types.Crewmate, cs(Shifter.color, "Shifter"), rates, null, true);
+ shifterShiftsModifiers = CustomOption.Create(71, Types.Crewmate, "Shifter Shifts Modifiers", false, shifterSpawnRate);
+
+ mayorSpawnRate = CustomOption.Create(80, Types.Crewmate, cs(Mayor.color, "Mayor"), rates, null, true);
+
+ mayorCanSeeVoteColors = CustomOption.Create(81, Types.Crewmate, "Mayor Can See Vote Colors", false, mayorSpawnRate);
+ mayorTasksNeededToSeeVoteColors = CustomOption.Create(82, Types.Crewmate, "Completed Tasks Needed To See Vote Colors", 5f, 0f, 20f, 1f, mayorCanSeeVoteColors);
+
+ engineerSpawnRate = CustomOption.Create(90, Types.Crewmate, cs(Engineer.color, "Engineer"), rates, null, true);
+ engineerNumberOfFixes = CustomOption.Create(91, Types.Crewmate, "Number Of Sabotage Fixes", 1f, 1f, 3f, 1f, engineerSpawnRate);
+ engineerHighlightForImpostors = CustomOption.Create(92, Types.Crewmate, "Impostors See Vents Highlighted", true, engineerSpawnRate);
+ engineerHighlightForTeamJackal = CustomOption.Create(93, Types.Crewmate, "Jackal and Sidekick See Vents Highlighted ", true, engineerSpawnRate);
+
+ sheriffSpawnRate = CustomOption.Create(100, Types.Crewmate, cs(Sheriff.color, "Sheriff"), rates, null, true);
+ sheriffCooldown = CustomOption.Create(101, Types.Crewmate, "Sheriff Cooldown", 30f, 10f, 60f, 2.5f, sheriffSpawnRate);
+ sheriffCanKillNeutrals = CustomOption.Create(102, Types.Crewmate, "Sheriff Can Kill Neutrals", false, sheriffSpawnRate);
+ deputySpawnRate = CustomOption.Create(103, Types.Crewmate, "Sheriff Has A Deputy", rates, sheriffSpawnRate);
+ deputyNumberOfHandcuffs = CustomOption.Create(104, Types.Crewmate, "Deputy Number Of Handcuffs", 3f, 1f, 10f, 1f, deputySpawnRate);
+ deputyHandcuffCooldown = CustomOption.Create(105, Types.Crewmate, "Handcuff Cooldown", 30f, 10f, 60f, 2.5f, deputySpawnRate);
+ deputyHandcuffDuration = CustomOption.Create(106, Types.Crewmate, "Handcuff Duration", 15f, 5f, 60f, 2.5f, deputySpawnRate);
+ deputyKnowsSheriff = CustomOption.Create(107, Types.Crewmate, "Sheriff And Deputy Know Each Other ", true, deputySpawnRate);
+ deputyGetsPromoted = CustomOption.Create(108, Types.Crewmate, "Deputy Gets Promoted To Sheriff", new string[] { "Off", "On (Immediately)", "On (After Meeting)" }, deputySpawnRate);
+ deputyKeepsHandcuffs = CustomOption.Create(109, Types.Crewmate, "Deputy Keeps Handcuffs When Promoted", true, deputyGetsPromoted);
+
+ lighterSpawnRate = CustomOption.Create(110, Types.Crewmate, cs(Lighter.color, "Lighter"), rates, null, true);
+ lighterModeLightsOnVision = CustomOption.Create(111, Types.Crewmate, "Lighter Mode Vision On Lights On", 2f, 0.25f, 5f, 0.25f, lighterSpawnRate);
+ lighterModeLightsOffVision = CustomOption.Create(112, Types.Crewmate, "Lighter Mode Vision On Lights Off", 0.75f, 0.25f, 5f, 0.25f, lighterSpawnRate);
+ lighterCooldown = CustomOption.Create(113, Types.Crewmate, "Lighter Cooldown", 30f, 5f, 120f, 5f, lighterSpawnRate);
+ lighterDuration = CustomOption.Create(114, Types.Crewmate, "Lighter Duration", 5f, 2.5f, 60f, 2.5f, lighterSpawnRate);
+
+ detectiveSpawnRate = CustomOption.Create(120, Types.Crewmate, cs(Detective.color, "Detective"), rates, null, true);
+ detectiveAnonymousFootprints = CustomOption.Create(121, Types.Crewmate, "Anonymous Footprints", false, detectiveSpawnRate);
+ detectiveFootprintIntervall = CustomOption.Create(122, Types.Crewmate, "Footprint Intervall", 0.5f, 0.25f, 10f, 0.25f, detectiveSpawnRate);
+ detectiveFootprintDuration = CustomOption.Create(123, Types.Crewmate, "Footprint Duration", 5f, 0.25f, 10f, 0.25f, detectiveSpawnRate);
+ detectiveReportNameDuration = CustomOption.Create(124, Types.Crewmate, "Time Where Detective Reports Will Have Name", 0, 0, 60, 2.5f, detectiveSpawnRate);
+ detectiveReportColorDuration = CustomOption.Create(125, Types.Crewmate, "Time Where Detective Reports Will Have Color Type", 20, 0, 120, 2.5f, detectiveSpawnRate);
+
+ timeMasterSpawnRate = CustomOption.Create(130, Types.Crewmate, cs(TimeMaster.color, "Time Master"), rates, null, true);
+ timeMasterCooldown = CustomOption.Create(131, Types.Crewmate, "Time Master Cooldown", 30f, 10f, 120f, 2.5f, timeMasterSpawnRate);
+ timeMasterRewindTime = CustomOption.Create(132, Types.Crewmate, "Rewind Time", 3f, 1f, 10f, 1f, timeMasterSpawnRate);
+ timeMasterShieldDuration = CustomOption.Create(133, Types.Crewmate, "Time Master Shield Duration", 3f, 1f, 20f, 1f, timeMasterSpawnRate);
+
+ medicSpawnRate = CustomOption.Create(140, Types.Crewmate, cs(Medic.color, "Medic"), rates, null, true);
+ medicShowShielded = CustomOption.Create(143, Types.Crewmate, "Show Shielded Player", new string[] {"Everyone", "Shielded + Medic", "Medic"}, medicSpawnRate);
+ medicShowAttemptToShielded = CustomOption.Create(144, Types.Crewmate, "Shielded Player Sees Murder Attempt", false, medicSpawnRate);
+ medicSetOrShowShieldAfterMeeting = CustomOption.Create(145, Types.Crewmate, "Shield Will Be Activated", new string[] { "Instantly", "Instantly, Visible\nAfter Meeting", "After Meeting" }, medicSpawnRate);
+
+ medicShowAttemptToMedic = CustomOption.Create(146, Types.Crewmate, "Medic Sees Murder Attempt On Shielded Player", false, medicSpawnRate);
+
+ swapperSpawnRate = CustomOption.Create(150, Types.Crewmate, cs(Swapper.color, "Swapper"), rates, null, true);
+ swapperCanCallEmergency = CustomOption.Create(151, Types.Crewmate, "Swapper Can Call Emergency Meeting", false, swapperSpawnRate);
+ swapperCanOnlySwapOthers = CustomOption.Create(152, Types.Crewmate, "Swapper Can Only Swap Others", false, swapperSpawnRate);
+
+ swapperSwapsNumber = CustomOption.Create(153, Types.Crewmate, "Initial Swap Charges", 1f, 0f, 5f, 1f, swapperSpawnRate);
+ swapperRechargeTasksNumber = CustomOption.Create(154, Types.Crewmate, "Number Of Tasks Needed For Recharging", 2f, 1f, 10f, 1f, swapperSpawnRate);
+
+
+ seerSpawnRate = CustomOption.Create(160, Types.Crewmate, cs(Seer.color, "Seer"), rates, null, true);
+ seerMode = CustomOption.Create(161, Types.Crewmate, "Seer Mode", new string[]{ "Show Death Flash + Souls", "Show Death Flash", "Show Souls"}, seerSpawnRate);
+ seerLimitSoulDuration = CustomOption.Create(163, Types.Crewmate, "Seer Limit Soul Duration", false, seerSpawnRate);
+ seerSoulDuration = CustomOption.Create(162, Types.Crewmate, "Seer Soul Duration", 15f, 0f, 120f, 5f, seerLimitSoulDuration);
- hackerSpawnRate = CustomOption.Create(170, cs(Hacker.color, "Hacker"), rates, null, true);
- hackerCooldown = CustomOption.Create(171, "Hacker Cooldown", 30f, 5f, 60f, 5f, hackerSpawnRate);
- hackerHackeringDuration = CustomOption.Create(172, "Hacker Duration", 10f, 2.5f, 60f, 2.5f, hackerSpawnRate);
- hackerOnlyColorType = CustomOption.Create(173, "Hacker Only Sees Color Type", false, hackerSpawnRate);
- hackerToolsNumber = CustomOption.Create(174, "Max Mobile Gadget Charges", 5f, 1f, 30f, 1f, hackerSpawnRate);
- hackerRechargeTasksNumber = CustomOption.Create(175, "Number Of Tasks Needed For Recharging", 2f, 1f, 5f, 1f, hackerSpawnRate);
- hackerNoMove = CustomOption.Create(176, "Cant Move During Mobile Gadget Duration", true, hackerSpawnRate);
-
- trackerSpawnRate = CustomOption.Create(200, cs(Tracker.color, "Tracker"), rates, null, true);
- trackerUpdateIntervall = CustomOption.Create(201, "Tracker Update Intervall", 5f, 1f, 30f, 1f, trackerSpawnRate);
- trackerResetTargetAfterMeeting = CustomOption.Create(202, "Tracker Reset Target After Meeting", false, trackerSpawnRate);
- trackerCanTrackCorpses = CustomOption.Create(203, "Tracker Can Track Corpses", true, trackerSpawnRate);
- trackerCorpsesTrackingCooldown = CustomOption.Create(204, "Corpses Tracking Cooldown", 30f, 5f, 120f, 5f, trackerCanTrackCorpses);
- trackerCorpsesTrackingDuration = CustomOption.Create(205, "Corpses Tracking Duration", 5f, 2.5f, 30f, 2.5f, trackerCanTrackCorpses);
+ hackerSpawnRate = CustomOption.Create(170, Types.Crewmate, cs(Hacker.color, "Hacker"), rates, null, true);
+ hackerCooldown = CustomOption.Create(171, Types.Crewmate, "Hacker Cooldown", 30f, 5f, 60f, 5f, hackerSpawnRate);
+ hackerHackeringDuration = CustomOption.Create(172, Types.Crewmate, "Hacker Duration", 10f, 2.5f, 60f, 2.5f, hackerSpawnRate);
+ hackerOnlyColorType = CustomOption.Create(173, Types.Crewmate, "Hacker Only Sees Color Type", false, hackerSpawnRate);
+ hackerToolsNumber = CustomOption.Create(174, Types.Crewmate, "Max Mobile Gadget Charges", 5f, 1f, 30f, 1f, hackerSpawnRate);
+ hackerRechargeTasksNumber = CustomOption.Create(175, Types.Crewmate, "Number Of Tasks Needed For Recharging", 2f, 1f, 5f, 1f, hackerSpawnRate);
+ hackerNoMove = CustomOption.Create(176, Types.Crewmate, "Cant Move During Mobile Gadget Duration", true, hackerSpawnRate);
+
+ trackerSpawnRate = CustomOption.Create(200, Types.Crewmate, cs(Tracker.color, "Tracker"), rates, null, true);
+ trackerUpdateIntervall = CustomOption.Create(201, Types.Crewmate, "Tracker Update Intervall", 5f, 1f, 30f, 1f, trackerSpawnRate);
+ trackerResetTargetAfterMeeting = CustomOption.Create(202, Types.Crewmate, "Tracker Reset Target After Meeting", false, trackerSpawnRate);
+ trackerCanTrackCorpses = CustomOption.Create(203, Types.Crewmate, "Tracker Can Track Corpses", true, trackerSpawnRate);
+ trackerCorpsesTrackingCooldown = CustomOption.Create(204, Types.Crewmate, "Corpses Tracking Cooldown", 30f, 5f, 120f, 5f, trackerCanTrackCorpses);
+ trackerCorpsesTrackingDuration = CustomOption.Create(205, Types.Crewmate, "Corpses Tracking Duration", 5f, 2.5f, 30f, 2.5f, trackerCanTrackCorpses);
- snitchSpawnRate = CustomOption.Create(210, cs(Snitch.color, "Snitch"), rates, null, true);
- snitchLeftTasksForReveal = CustomOption.Create(211, "Task Count Where The Snitch Will Be Revealed", 1f, 0f, 5f, 1f, snitchSpawnRate);
- snitchIncludeTeamJackal = CustomOption.Create(212, "Include Team Jackal", false, snitchSpawnRate);
- snitchTeamJackalUseDifferentArrowColor = CustomOption.Create(213, "Use Different Arrow Color For Team Jackal", true, snitchIncludeTeamJackal);
-
- spySpawnRate = CustomOption.Create(240, cs(Spy.color, "Spy"), rates, null, true);
- spyCanDieToSheriff = CustomOption.Create(241, "Spy Can Die To Sheriff", false, spySpawnRate);
- spyImpostorsCanKillAnyone = CustomOption.Create(242, "Impostors Can Kill Anyone If There Is A Spy", true, spySpawnRate);
- spyCanEnterVents = CustomOption.Create(243, "Spy Can Enter Vents", false, spySpawnRate);
- spyHasImpostorVision = CustomOption.Create(244, "Spy Has Impostor Vision", false, spySpawnRate);
-
- securityGuardSpawnRate = CustomOption.Create(280, cs(SecurityGuard.color, "Security Guard"), rates, null, true);
- securityGuardCooldown = CustomOption.Create(281, "Security Guard Cooldown", 30f, 10f, 60f, 2.5f, securityGuardSpawnRate);
- securityGuardTotalScrews = CustomOption.Create(282, "Security Guard Number Of Screws", 7f, 1f, 15f, 1f, securityGuardSpawnRate);
- securityGuardCamPrice = CustomOption.Create(283, "Number Of Screws Per Cam", 2f, 1f, 15f, 1f, securityGuardSpawnRate);
- securityGuardVentPrice = CustomOption.Create(284, "Number Of Screws Per Vent", 1f, 1f, 15f, 1f, securityGuardSpawnRate);
- securityGuardCamDuration = CustomOption.Create(285, "Security Guard Duration", 10f, 2.5f, 60f, 2.5f, securityGuardSpawnRate);
- securityGuardCamMaxCharges = CustomOption.Create(286, "Gadged Max Charges", 5f, 1f, 30f, 1f, securityGuardSpawnRate);
- securityGuardCamRechargeTasksNumber = CustomOption.Create(287, "Number Of Tasks Needed For Recharging", 3f, 1f, 10f, 1f, securityGuardSpawnRate);
- securityGuardNoMove = CustomOption.Create(288, "Cant Move During Cam Duration", true, securityGuardSpawnRate);
-
- baitSpawnRate = CustomOption.Create(330, cs(Bait.color, "Bait"), rates, null, true);
- baitHighlightAllVents = CustomOption.Create(331, "Highlight All Vents If A Vent Is Occupied", false, baitSpawnRate);
- baitReportDelay = CustomOption.Create(332, "Bait Report Delay", 0f, 0f, 10f, 1f, baitSpawnRate);
- baitShowKillFlash = CustomOption.Create(333, "Warn The Killer With A Flash", true, baitSpawnRate);
-
- mediumSpawnRate = CustomOption.Create(360, cs(Medium.color, "Medium"), rates, null, true);
- mediumCooldown = CustomOption.Create(361, "Medium Questioning Cooldown", 30f, 5f, 120f, 5f, mediumSpawnRate);
- mediumDuration = CustomOption.Create(362, "Medium Questioning Duration", 3f, 0f, 15f, 1f, mediumSpawnRate);
- mediumOneTimeUse = CustomOption.Create(363, "Each Soul Can Only Be Questioned Once", false, mediumSpawnRate);
+ snitchSpawnRate = CustomOption.Create(210, Types.Crewmate, cs(Snitch.color, "Snitch"), rates, null, true);
+ snitchLeftTasksForReveal = CustomOption.Create(211, Types.Crewmate, "Task Count Where The Snitch Will Be Revealed", 1f, 0f, 5f, 1f, snitchSpawnRate);
+ snitchIncludeTeamJackal = CustomOption.Create(212, Types.Crewmate, "Include Team Jackal", false, snitchSpawnRate);
+ snitchTeamJackalUseDifferentArrowColor = CustomOption.Create(213, Types.Crewmate, "Use Different Arrow Color For Team Jackal", true, snitchIncludeTeamJackal);
+
+ spySpawnRate = CustomOption.Create(240, Types.Crewmate, cs(Spy.color, "Spy"), rates, null, true);
+ spyCanDieToSheriff = CustomOption.Create(241, Types.Crewmate, "Spy Can Die To Sheriff", false, spySpawnRate);
+ spyImpostorsCanKillAnyone = CustomOption.Create(242, Types.Crewmate, "Impostors Can Kill Anyone If There Is A Spy", true, spySpawnRate);
+ spyCanEnterVents = CustomOption.Create(243, Types.Crewmate, "Spy Can Enter Vents", false, spySpawnRate);
+ spyHasImpostorVision = CustomOption.Create(244, Types.Crewmate, "Spy Has Impostor Vision", false, spySpawnRate);
+
+ portalmakerSpawnRate = CustomOption.Create(390, Types.Crewmate, cs(Portalmaker.color, "Portalmaker"), rates, null, true);
+ portalmakerCooldown = CustomOption.Create(391, Types.Crewmate, "Portalmaker Cooldown", 30f, 10f, 60f, 2.5f, portalmakerSpawnRate);
+ portalmakerUsePortalCooldown = CustomOption.Create(392, Types.Crewmate, "Use Portal Cooldown", 30f, 10f, 60f, 2.5f, portalmakerSpawnRate);
+ portalmakerLogOnlyColorType = CustomOption.Create(393, Types.Crewmate, "Portalmaker Log Only Shows Color Type", true, portalmakerSpawnRate);
+ portalmakerLogHasTime = CustomOption.Create(394, Types.Crewmate, "Log Shows Time", true, portalmakerSpawnRate);
+ securityGuardSpawnRate = CustomOption.Create(280, Types.Crewmate, cs(SecurityGuard.color, "Security Guard"), rates, null, true);
+ securityGuardCooldown = CustomOption.Create(281, Types.Crewmate, "Security Guard Cooldown", 30f, 10f, 60f, 2.5f, securityGuardSpawnRate);
+ securityGuardTotalScrews = CustomOption.Create(282, Types.Crewmate, "Security Guard Number Of Screws", 7f, 1f, 15f, 1f, securityGuardSpawnRate);
+ securityGuardCamPrice = CustomOption.Create(283, Types.Crewmate, "Number Of Screws Per Cam", 2f, 1f, 15f, 1f, securityGuardSpawnRate);
+ securityGuardVentPrice = CustomOption.Create(284, Types.Crewmate, "Number Of Screws Per Vent", 1f, 1f, 15f, 1f, securityGuardSpawnRate);
+ securityGuardCamDuration = CustomOption.Create(285, Types.Crewmate, "Security Guard Duration", 10f, 2.5f, 60f, 2.5f, securityGuardSpawnRate);
+ securityGuardCamMaxCharges = CustomOption.Create(286, Types.Crewmate, "Gadged Max Charges", 5f, 1f, 30f, 1f, securityGuardSpawnRate);
+ securityGuardCamRechargeTasksNumber = CustomOption.Create(287, Types.Crewmate, "Number Of Tasks Needed For Recharging", 3f, 1f, 10f, 1f, securityGuardSpawnRate);
+ securityGuardNoMove = CustomOption.Create(288, Types.Crewmate, "Cant Move During Cam Duration", true, securityGuardSpawnRate);
+
+ mediumSpawnRate = CustomOption.Create(360, Types.Crewmate, cs(Medium.color, "Medium"), rates, null, true);
+ mediumCooldown = CustomOption.Create(361, Types.Crewmate, "Medium Questioning Cooldown", 30f, 5f, 120f, 5f, mediumSpawnRate);
+ mediumDuration = CustomOption.Create(362, Types.Crewmate, "Medium Questioning Duration", 3f, 0f, 15f, 1f, mediumSpawnRate);
+ mediumOneTimeUse = CustomOption.Create(363, Types.Crewmate, "Each Soul Can Only Be Questioned Once", false, mediumSpawnRate);
+
+ // Modifier
+ modifierBloody = CustomOption.Create(1000, Types.Modifier, cs(Color.yellow, "Bloody"), rates, null, true);
+ modifierBloodyQuantity = CustomOption.Create(1001, Types.Modifier, cs(Color.yellow, "Bloody Quantity"), ratesModifier, modifierBloody);
+ modifierBloodyDuration = CustomOption.Create(1002, Types.Modifier, "Trail Duration", 10f, 3f, 60f, 1f, modifierBloody);
+
+ modifierAntiTeleport = CustomOption.Create(1010, Types.Modifier, cs(Color.yellow, "Anti Teleport"), rates, null, true);
+ modifierAntiTeleportQuantity = CustomOption.Create(1011, Types.Modifier, cs(Color.yellow, "Anti Teleport Quantity"), ratesModifier, modifierAntiTeleport);
+
+ modifierTieBreaker = CustomOption.Create(1020, Types.Modifier, cs(Color.yellow, "Tie Breaker"), rates, null, true);
+
+ modifierBait = CustomOption.Create(1030, Types.Modifier, cs(Color.yellow, "Bait"), rates, null, true);
+ modifierBaitQuantity = CustomOption.Create(1031, Types.Modifier, cs(Color.yellow, "Bait Quantity"), ratesModifier, modifierBait);
+ modifierBaitReportDelayMin = CustomOption.Create(1032, Types.Modifier, "Bait Report Delay Min", 0f, 0f, 10f, 1f, modifierBait);
+ modifierBaitReportDelayMax = CustomOption.Create(1033, Types.Modifier, "Bait Report Delay Max", 0f, 0f, 10f, 1f, modifierBait);
+ modifierBaitShowKillFlash = CustomOption.Create(1034, Types.Modifier, "Warn The Killer With A Flash", true, modifierBait);
+
+ modifierLover = CustomOption.Create(1040, Types.Modifier, cs(Color.yellow, "Lovers"), rates, null, true);
+ modifierLoverImpLoverRate = CustomOption.Create(1041, Types.Modifier, "Chance That One Lover Is Impostor", rates, modifierLover);
+ modifierLoverBothDie = CustomOption.Create(1042, Types.Modifier, "Both Lovers Die", true, modifierLover);
+ modifierLoverEnableChat = CustomOption.Create(1043, Types.Modifier, "Enable Lover Chat", true, modifierLover);
+
+ modifierSunglasses = CustomOption.Create(1050, Types.Modifier, cs(Color.yellow, "Sunglasses"), rates, null, true);
+ modifierSunglassesQuantity = CustomOption.Create(1051, Types.Modifier, cs(Color.yellow, "Sunglasses Quantity"), ratesModifier, modifierSunglasses);
+ modifierSunglassesVision = CustomOption.Create(1052, Types.Modifier, "Vision With Sunglasses", new string[] { "-10%", "-20%", "-30%", "-40%", "-50%" }, modifierSunglasses);
+
+ modifierMini = CustomOption.Create(1061, Types.Modifier, cs(Color.yellow, "Mini"), rates, null, true);
+ modifierMiniGrowingUpDuration = CustomOption.Create(1062, Types.Modifier, "Mini Growing Up Duration", 400f, 100f, 1500f, 100f, modifierMini);
+
+ modifierVip = CustomOption.Create(1070, Types.Modifier, cs(Color.yellow, "VIP"), rates, null, true);
+ modifierVipQuantity = CustomOption.Create(1071, Types.Modifier, cs(Color.yellow, "VIP Quantity"), ratesModifier, modifierVip);
+ modifierVipShowColor = CustomOption.Create(1072, Types.Modifier, "Show Team Color", true, modifierVip);
+
+ modifierInvert = CustomOption.Create(1080, Types.Modifier, cs(Color.yellow, "Invert"), rates, null, true);
+ modifierInvertQuantity = CustomOption.Create(1081, Types.Modifier, cs(Color.yellow, "Modifier Quantity"), ratesModifier, modifierInvert);
+ modifierInvertDuration = CustomOption.Create(1082, Types.Modifier, "Number Of Meetings Inverted", 3f, 1f, 15f, 1f, modifierInvert);
// Other options
- maxNumberOfMeetings = CustomOption.Create(3, "Number Of Meetings (excluding Mayor meeting)", 10, 0, 15, 1, null, true);
- blockSkippingInEmergencyMeetings = CustomOption.Create(4, "Block Skipping In Emergency Meetings", false);
- noVoteIsSelfVote = CustomOption.Create(5, "No Vote Is Self Vote", false, blockSkippingInEmergencyMeetings);
- hidePlayerNames = CustomOption.Create(6, "Hide Player Names", false);
- allowParallelMedBayScans = CustomOption.Create(7, "Allow Parallel MedBay Scans", false);
-
- dynamicMap = CustomOption.Create(8, "Play On A Random Map", false, null, false);
- dynamicMapEnableSkeld = CustomOption.Create(501, "Enable Skeld Rotation", true, dynamicMap, false);
- dynamicMapEnableMira = CustomOption.Create(502, "Enable Mira Rotation", true, dynamicMap, false);
- dynamicMapEnablePolus = CustomOption.Create(503, "Enable Polus Rotation", true, dynamicMap, false);
- dynamicMapEnableAirShip = CustomOption.Create(504, "Enable Airship Rotation", true, dynamicMap, false);
+ maxNumberOfMeetings = CustomOption.Create(3, Types.General, "Number Of Meetings (excluding Mayor meeting)", 10, 0, 15, 1, null, true);
+ blockSkippingInEmergencyMeetings = CustomOption.Create(4, Types.General, "Block Skipping In Emergency Meetings", false);
+ noVoteIsSelfVote = CustomOption.Create(5, Types.General, "No Vote Is Self Vote", false, blockSkippingInEmergencyMeetings);
+ hidePlayerNames = CustomOption.Create(6, Types.General, "Hide Player Names", false);
+ allowParallelMedBayScans = CustomOption.Create(7, Types.General, "Allow Parallel MedBay Scans", false);
+ shieldFirstKill = CustomOption.Create(8, Types.General, "Shield Last Game First Kill", false);
+
+ dynamicMap = CustomOption.Create(500, Types.General, "Play On A Random Map", false, null, false);
+ dynamicMapEnableSkeld = CustomOption.Create(501, Types.General, "Enable Skeld Rotation", true, dynamicMap, false);
+ dynamicMapEnableMira = CustomOption.Create(502, Types.General, "Enable Mira Rotation", true, dynamicMap, false);
+ dynamicMapEnablePolus = CustomOption.Create(503, Types.General, "Enable Polus Rotation", true, dynamicMap, false);
+ dynamicMapEnableAirShip = CustomOption.Create(504, Types.General, "Enable Airship Rotation", true, dynamicMap, false);
blockedRolePairings.Add((byte)RoleId.Vampire, new [] { (byte)RoleId.Warlock});
blockedRolePairings.Add((byte)RoleId.Warlock, new [] { (byte)RoleId.Vampire});
diff --git a/TheOtherRoles/Helpers.cs b/TheOtherRoles/Helpers.cs
index 87c6f952c..f1541fff8 100644
--- a/TheOtherRoles/Helpers.cs
+++ b/TheOtherRoles/Helpers.cs
@@ -125,6 +125,8 @@ public static void refreshRoleDescription(PlayerControl player) {
if (roleInfo.name == "Jackal") {
var getSidekickText = Jackal.canCreateSidekick ? " and recruit a Sidekick" : "";
task.Text = cs(roleInfo.color, $"{roleInfo.name}: Kill everyone{getSidekickText}");
+ } else if (roleInfo.name == "Invert") {
+ task.Text = cs(roleInfo.color, $"{roleInfo.name}: {roleInfo.shortDescription} ({Invert.meetings})");
} else {
task.Text = cs(roleInfo.color, $"{roleInfo.name}: {roleInfo.shortDescription}");
}
@@ -207,7 +209,7 @@ public static bool hidePlayerName(PlayerControl source, PlayerControl target) {
else if (!MapOptions.hidePlayerNames) return false; // All names are visible
else if (source == null || target == null) return true;
else if (source == target) return false; // Player sees his own name
- else if (source.Data.Role.IsImpostor && (target.Data.Role.IsImpostor || target == Spy.spy)) return false; // Members of team Impostors see the names of Impostors/Spies
+ else if (source.Data.Role.IsImpostor && (target.Data.Role.IsImpostor || target == Spy.spy || target == Sidekick.sidekick && Sidekick.wasTeamRed || target == Jackal.jackal && Jackal.wasTeamRed)) return false; // Members of team Impostors see the names of Impostors/Spies
else if ((source == Lovers.lover1 || source == Lovers.lover2) && (target == Lovers.lover1 || target == Lovers.lover2)) return false; // Members of team Lovers see the names of each other
else if ((source == Jackal.jackal || source == Sidekick.sidekick) && (target == Jackal.jackal || target == Sidekick.sidekick || target == Jackal.fakeSidekick)) return false; // Members of team Jackal see the names of each other
else if (Deputy.knowsSheriff && (source == Sheriff.sheriff || source == Deputy.deputy) && (target == Sheriff.sheriff || target == Deputy.deputy)) return false; // Sheriff & Deputy see the names of each other
@@ -237,6 +239,8 @@ public static void setLook(this PlayerControl target, String playerName, int col
else clip = nextSkin.IdleAnim;
float progress = playerPhysics.Animator.m_animator.GetCurrentAnimatorStateInfo(0).normalizedTime;
playerPhysics.Skin.skin = nextSkin;
+ if (playerPhysics.Skin.layer.material == DestroyableSingleton.Instance.PlayerMaterial)
+ PlayerControl.SetPlayerMaterialColors(colorId, playerPhysics.Skin.layer);
spriteAnim.Play(clip, 1f);
spriteAnim.m_animator.Play("a", 0, progress % 1);
spriteAnim.m_animator.Update(0f);
@@ -296,6 +300,9 @@ public static MurderAttemptResult checkMuderAttempt(PlayerControl killer, Player
if (killer == null || killer.Data == null || killer.Data.IsDead || killer.Data.Disconnected) return MurderAttemptResult.SuppressKill; // Allow non Impostor kills compared to vanilla code
if (target == null || target.Data == null || target.Data.IsDead || target.Data.Disconnected) return MurderAttemptResult.SuppressKill; // Allow killing players in vents compared to vanilla code
+ // Handle first kill attempt
+ if (MapOptions.shieldFirstKill && MapOptions.firstKillPlayer == target) return MurderAttemptResult.SuppressKill;
+
// Handle blank shot
if (Pursuer.blankedList.Any(x => x.PlayerId == killer.PlayerId)) {
MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.SetBlanked, Hazel.SendOption.Reliable, -1);
diff --git a/TheOtherRoles/Main.cs b/TheOtherRoles/Main.cs
index f8b414411..2976ea871 100644
--- a/TheOtherRoles/Main.cs
+++ b/TheOtherRoles/Main.cs
@@ -21,7 +21,7 @@ namespace TheOtherRoles
public class TheOtherRolesPlugin : BasePlugin
{
public const string Id = "me.eisbison.theotherroles";
- public const string VersionString = "3.4.5";
+ public const string VersionString = "4.0.0";
public static System.Version Version = System.Version.Parse(VersionString);
internal static BepInEx.Logging.ManualLogSource Logger;
@@ -29,12 +29,13 @@ public class TheOtherRolesPlugin : BasePlugin
public Harmony Harmony { get; } = new Harmony(Id);
public static TheOtherRolesPlugin Instance;
- public static int optionsPage = 1;
+ public static int optionsPage = 2;
public static ConfigEntry DebugMode { get; private set; }
public static ConfigEntry StreamerMode { get; set; }
public static ConfigEntry GhostsSeeTasks { get; set; }
public static ConfigEntry GhostsSeeRoles { get; set; }
+ public static ConfigEntry GhostsSeeModifier { get; set; }
public static ConfigEntry GhostsSeeVotes{ get; set; }
public static ConfigEntry ShowRoleSummary { get; set; }
public static ConfigEntry ShowLighterDarker { get; set; }
@@ -64,6 +65,7 @@ public override void Load() {
StreamerMode = Config.Bind("Custom", "Enable Streamer Mode", false);
GhostsSeeTasks = Config.Bind("Custom", "Ghosts See Remaining Tasks", true);
GhostsSeeRoles = Config.Bind("Custom", "Ghosts See Roles", true);
+ GhostsSeeModifier = Config.Bind("Custom", "Ghosts See Modifier", true);
GhostsSeeVotes = Config.Bind("Custom", "Ghosts See Votes", true);
ShowRoleSummary = Config.Bind("Custom", "Show Role Summary", true);
ShowLighterDarker = Config.Bind("Custom", "Show Lighter / Darker", true);
@@ -86,7 +88,7 @@ public override void Load() {
Instance = this;
CustomOptionHolder.Load();
CustomColors.Load();
-
+ Patches.FreeNamePatch.Initialize();
Harmony.PatchAll();
}
public static Sprite GetModStamp() {
diff --git a/TheOtherRoles/MapOptions.cs b/TheOtherRoles/MapOptions.cs
index 49b66694e..e2b165f79 100644
--- a/TheOtherRoles/MapOptions.cs
+++ b/TheOtherRoles/MapOptions.cs
@@ -12,18 +12,22 @@ static class MapOptions {
public static bool noVoteIsSelfVote = false;
public static bool hidePlayerNames = false;
public static bool ghostsSeeRoles = true;
+ public static bool ghostsSeeModifier = true;
public static bool ghostsSeeTasks = true;
public static bool ghostsSeeVotes = true;
public static bool showRoleSummary = true;
public static bool allowParallelMedBayScans = false;
public static bool showLighterDarker = true;
public static bool enableHorseMode = false;
+ public static bool shieldFirstKill = false;
// Updating values
public static int meetingsCount = 0;
public static List camerasToAdd = new List();
public static List ventsToSeal = new List();
public static Dictionary playerIcons = new Dictionary();
+ public static string firstKillName;
+ public static PlayerControl firstKillPlayer;
public static void clearAndReloadMapOptions() {
meetingsCount = 0;
@@ -36,10 +40,13 @@ public static void clearAndReloadMapOptions() {
noVoteIsSelfVote = CustomOptionHolder.noVoteIsSelfVote.getBool();
hidePlayerNames = CustomOptionHolder.hidePlayerNames.getBool();
allowParallelMedBayScans = CustomOptionHolder.allowParallelMedBayScans.getBool();
+ shieldFirstKill = CustomOptionHolder.shieldFirstKill.getBool();
+ firstKillPlayer = null;
}
public static void reloadPluginOptions() {
ghostsSeeRoles = TheOtherRolesPlugin.GhostsSeeRoles.Value;
+ ghostsSeeModifier = TheOtherRolesPlugin.GhostsSeeModifier.Value;
ghostsSeeTasks = TheOtherRolesPlugin.GhostsSeeTasks.Value;
ghostsSeeVotes = TheOtherRolesPlugin.GhostsSeeVotes.Value;
showRoleSummary = TheOtherRolesPlugin.ShowRoleSummary.Value;
@@ -48,4 +55,4 @@ public static void reloadPluginOptions() {
Patches.ShouldAlwaysHorseAround.isHorseMode = TheOtherRolesPlugin.EnableHorseMode.Value;
}
}
-}
\ No newline at end of file
+}
diff --git a/TheOtherRoles/Modules/ChatCommands.cs b/TheOtherRoles/Modules/ChatCommands.cs
index 6f34cdd9e..2631a797b 100644
--- a/TheOtherRoles/Modules/ChatCommands.cs
+++ b/TheOtherRoles/Modules/ChatCommands.cs
@@ -88,7 +88,7 @@ public static void Postfix(HudManager __instance) {
public static class SetBubbleName {
public static void Postfix(ChatBubble __instance, [HarmonyArgument(0)] string playerName) {
PlayerControl sourcePlayer = PlayerControl.AllPlayerControls.ToArray().ToList().FirstOrDefault(x => x.Data.PlayerName.Equals(playerName));
- if (PlayerControl.LocalPlayer != null && PlayerControl.LocalPlayer.Data.Role.IsImpostor && Spy.spy != null && sourcePlayer.PlayerId == Spy.spy.PlayerId && __instance != null) __instance.NameText.color = Palette.ImpostorRed;
+ if (PlayerControl.LocalPlayer != null && PlayerControl.LocalPlayer.Data.Role.IsImpostor && (Spy.spy != null && sourcePlayer.PlayerId == Spy.spy.PlayerId || Sidekick.sidekick != null && Sidekick.wasTeamRed && sourcePlayer.PlayerId == Sidekick.sidekick.PlayerId || Jackal.jackal != null && Jackal.wasTeamRed && sourcePlayer.PlayerId == Jackal.jackal.PlayerId) && __instance != null) __instance.NameText.color = Palette.ImpostorRed;
}
}
diff --git a/TheOtherRoles/Modules/CustomHats.cs b/TheOtherRoles/Modules/CustomHats.cs
index 0b86984e0..5cd1a0368 100644
--- a/TheOtherRoles/Modules/CustomHats.cs
+++ b/TheOtherRoles/Modules/CustomHats.cs
@@ -128,8 +128,7 @@ private static Sprite CreateHatSprite(string path, bool fromDisk = false) {
private static HatData CreateHatBehaviour(CustomHat ch, bool fromDisk = false, bool testOnly = false) {
if (hatShader == null) {
- Material tmpShader = new Material("PlayerMaterial");
- tmpShader.shader = Shader.Find("Unlit/PlayerShader");
+ Material tmpShader = DestroyableSingleton.Instance.PlayerMaterial;
hatShader = tmpShader;
}
diff --git a/TheOtherRoles/Modules/CustomOptions.cs b/TheOtherRoles/Modules/CustomOptions.cs
index 24589c703..4cc2e362c 100644
--- a/TheOtherRoles/Modules/CustomOptions.cs
+++ b/TheOtherRoles/Modules/CustomOptions.cs
@@ -11,6 +11,14 @@
namespace TheOtherRoles {
public class CustomOption {
+ public enum CustomOptionType {
+ General,
+ Impostor,
+ Neutral,
+ Crewmate,
+ Modifier
+ }
+
public static List options = new List();
public static int preset = 0;
@@ -24,10 +32,11 @@ public class CustomOption {
public OptionBehaviour optionBehaviour;
public CustomOption parent;
public bool isHeader;
+ public CustomOptionType type;
// Option creation
- public CustomOption(int id, string name, System.Object[] selections, System.Object defaultValue, CustomOption parent, bool isHeader) {
+ public CustomOption(int id, CustomOptionType type, string name, System.Object[] selections, System.Object defaultValue, CustomOption parent, bool isHeader) {
this.id = id;
this.name = parent == null ? name : "- " + name;
this.selections = selections;
@@ -35,6 +44,7 @@ public CustomOption(int id, string name, System.Object[] selections, System.Obj
this.defaultSelection = index >= 0 ? index : 0;
this.parent = parent;
this.isHeader = isHeader;
+ this.type = type;
selection = 0;
if (id != 0) {
entry = TheOtherRolesPlugin.Instance.Config.Bind($"Preset{preset}", id.ToString(), defaultSelection);
@@ -43,24 +53,24 @@ public CustomOption(int id, string name, System.Object[] selections, System.Obj
options.Add(this);
}
- public static CustomOption Create(int id, string name, string[] selections, CustomOption parent = null, bool isHeader = false) {
- return new CustomOption(id, name, selections, "", parent, isHeader);
+ public static CustomOption Create(int id, CustomOptionType type, string name, string[] selections, CustomOption parent = null, bool isHeader = false) {
+ return new CustomOption(id, type, name, selections, "", parent, isHeader);
}
- public static CustomOption Create(int id, string name, float defaultValue, float min, float max, float step, CustomOption parent = null, bool isHeader = false) {
+ public static CustomOption Create(int id, CustomOptionType type, string name, float defaultValue, float min, float max, float step, CustomOption parent = null, bool isHeader = false) {
List selections = new List();
for (float s = min; s <= max; s += step)
selections.Add(s);
- return new CustomOption(id, name, selections.Cast