From: Eisbison Date: Tue, 6 Apr 2021 12:29:53 +0000 (+0200) Subject: Version v2.0.0 beta X-Git-Url: https://git.deb.at/?a=commitdiff_plain;h=f406b2b349634ef3e2fd6b6dd28094c213b87762;p=rhonda%2Ftheotherroles.git Version v2.0.0 beta --- diff --git a/Preview_v1.8.png b/Preview_v1.8.png deleted file mode 100644 index e1eb147..0000000 Binary files a/Preview_v1.8.png and /dev/null differ diff --git a/Preview_v2.0.png b/Preview_v2.0.png new file mode 100644 index 0000000..6a76877 Binary files /dev/null and b/Preview_v2.0.png differ diff --git a/README.md b/README.md index 2d96dbb..adc3fe8 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ [![Discord](https://discord.com/assets/e4923594e694a21542a489471ecffa50.svg)](https://discord.gg/77RkMJHWsM) ![eisbison banner](./Banner.png) -![eisbison infographic](./Preview_v1.8.png) +![eisbison infographic](./Preview_v2.0.png) # The Other Roles -The **The Other Roles**, is a mod for Amongs Us which currently adds 20 additional roles to the game. +The **The Other Roles**, is a mod for Amongs Us which currently adds 25 additional roles and new [Settings](#settings) to the game. Even more roles are coming soon :) - [Mafia](#mafia) @@ -15,6 +15,7 @@ Even more roles are coming soon :) - [Morphling](#morphling) - [Camouflager](#camouflager) - [Vampire](#vampire) +- [Eraser](#eraser) - [Lovers](#lovers) - Lover - ImpLover @@ -25,9 +26,11 @@ Even more roles are coming soon :) - [Detective](#detective) - [Lighter](#lighter) - [Child](#child) + - Child Impostor + - Child Crewmate - [Medic](#medic) - [Mayor](#mayor) -- [Spy](#spy) +- [Hacker](#hacker) - [Shifter](#shifter) - [Time Master](#time-master) - [Swapper](#swapper) @@ -41,6 +44,7 @@ The [Role Assignment](#role-assignment) sections explains how the roles are bein # Releases | Among Us - Version| Mod Version | Link | |----------|-------------|-----------------| +| **2021.31.3s** | v2.0.0 beta | [Download](https://github.com/Eisbison/TheOtherRoles/releases/download/v2.0.0/TheOtherRoles.zip) | 2021.3.5s | v1.8.2 | [Download](https://github.com/Eisbison/TheOtherRoles/releases/download/v1.8.2/TheOtherRoles.zip) | 2021.3.5s | v1.8.1 | [Download](https://github.com/Eisbison/TheOtherRoles/releases/download/v1.8.1/TheOtherRoles.zip) | 2021.3.5s | v1.8 | [Download](https://github.com/Eisbison/TheOtherRoles/releases/download/v1.8/TheOtherRoles.zip) @@ -56,6 +60,24 @@ The [Role Assignment](#role-assignment) sections explains how the roles are bein
Click to show the Changelog +**Changes in 2.0.0** +- **New button art** created by **Bavari** +- **New mod updater/installer tool** created by [Narua](https://github.com/Narua2010) and [Jolle](https://github.com/joelweih). Check the [Installation](#installation) section for more details. +- **Custom options:** Introduced customizable presets. Starting with 2.0.0, settings can be copied and used with higher versions (2.0.0). +- **Time Master rework:** Check [Time Master](#time-master) for more information +- **Medic:** The Medic report changed, it only shows the time since death (see Detective) +- **Detective:** The Detective now sees the name/color type of the killer when he reports a dead body (ability moved from the Medic to the Detective) +- **Lighter:** We changed and tried to nerf the Lighter, see the [Lighter](#lighter) section for more details. +- **Seer:** As the role didn't work the way it was, we completely changed it. We're still working on the role, for now we're trying a few things. Check the [Seer](#seer) section to get more details about the new Seer. +- **Shifter:** We reworked the Shifter, he is now part of the crew. Check out the [Shifter](#shifter) sections for more details. +- **Hacker:** The Hacker is basically the old Spy. We added the option to only show the color type instead of the color on the admin table. +- **Camouflager:** Now also overrides the information of other roles, check the [Camouflager](#camouflager) section for more details. +- **Morphling:** Now also overrides the information of other roles, check the [Morphling](#morphling) section for more details +- **Child:** The Child can now be a Crewmate Child or an Impostor Child, check the [Child](#child) section for more details +- **Eraser:** The Eraser, a new Impostor role, is now part of the mod. Check the [Eraser](#eraser) section for more details +- **New options:** + - You can now set the maximum number of meetings in a game: Every player still only has one meeting. The Mayor can always use his meeting (even if the maximum number of meetings was reached). Impostor/Jackal meetings also count. + **Hotfix 1.8.2** - Add map and impostor count to lobby settings. - Fixed bugs where changing players to be the Sidekick didn't reset all the effects of their previous role. @@ -89,7 +111,7 @@ The [Role Assignment](#role-assignment) sections explains how the roles are bein - Time Master - Buff: He is not affected by his rewind anymore, which gives him more utility. Players will now be rewinded out of vents. - Child - Nerf: The child now grows up (see [child](#child)) and becomes a normal crewmate at some point. A growing child is not killable anymore. Some tasks are still not doable for the small child, we are working on that. But eventually when growing up it can do all the tasks as it's size increases. - Seer - Nerf: Added an option that sets how often the Seer mistakes the player for another. -- Spy - Nerf: The Spy now only sees the additional information when he activates his "Spy mode". That should stops the spy from camping the admin table/vitals. +- Hacker - Nerf: The Hacker now only sees the additional information when he activates his "Hacker mode". That should stops the hacker from camping the admin table/vitals. - Other: Camouflager/Morphling cooldowns were fixed. Custom regions code was removed to enable 3rd party tools. Some minor bugfixes. **Changes in v1.4:** @@ -111,8 +133,17 @@ The [Role Assignment](#role-assignment) sections explains how the roles are bein
# Installation -**Windows** -1. Download and unzip the newest [release](https://github.com/Eisbison/TheOtherRoles/releases/download/v1.8.2/TheOtherRoles.zip) +## Windows Auto Installation/Updateing Using The AmongUsModUpdater +This tool was made by [Narua](https://github.com/Narua2010) and [Jolle](https://github.com/joelweih). It automatically installs/updates the TheOtherRoles mod to the newest version, runs the game and +syncs your game options automatically. + +1. Simply get the newest [release](https://github.com/Narua2010/AmongUsModUpdater/releases/latest) of the [AmongUsModUpdater](https://github.com/Narua2010/AmongUsModUpdater) +2. Unzip the folder and run the **setup.exe** + +If you have problems with the AmongUsModUpdater, make sure To [contact us](https://discord.gg/csa3pHYdPU). + +## Windows Manual Installation +1. Download and unzip the newest [release](https://github.com/Eisbison/TheOtherRoles/releases/download/v2.0.0/TheOtherRoles.zip) 2. Find the folder of your game, for steams players you can right click in steam, on the game, a menu will appear proposing you to go to the folders. 3. Make a copy of your game, it's not obligatory but advise, put it where you want. 4. Drag or extract the files from the zip into your game, at the .exe level. @@ -122,9 +153,9 @@ Not working? You might want to install the dependency [vc_redist](https://aka.ms ![Install](https://i.imgur.com/pvBAyZN.png) -**Linux** +**Linux Manual** 1. Install Among Us via steam -2. Download newest [release](https://github.com/Eisbison/TheOtherRoles/releases/download/v1.8.2/TheOtherRoles.zip) and extract it to ~/.steam/steam/steamapps/common/Among Us +2. Download newest [release](https://github.com/Eisbison/TheOtherRoles/releases/download/v2.0.0/TheOtherRoles.zip) and extract it to ~/.steam/steam/steamapps/common/Among Us 3. Enable winhttp.dll via the proton winecfg (https://bepinex.github.io/bepinex_docs/master/articles/advanced/steam_interop.html#protonwine) 4. Launch the game via Steam @@ -133,10 +164,13 @@ We recommend you to play on custom servers rather than on the official ones. A g the *.dll* file into your Among Us/BepInEx/plugins folder and you're good to go. # Credits & Resources -[Reactor](https://github.com/NuclearPowered/Reactor) - The framework used\ +[Reactor](https://github.com/NuclearPowered/Reactor) - The framework used for all version before v2.0.0\ [BepInEx](https://github.com/BepInEx) - Used to hook game functions\ -[Essentials](https://github.com/DorCoMaNdO/Reactor-Essentials) - Custom game options by **DorCoMaNdO**. We made a few changes, which can be found on this [branch](https://github.com/Eisbison/Reactor-Essentials/tree/feature/TheOtherRoles-Adaption) of the fork.\ -[CooldownButton](https://github.com/DorCoMaNdO/Reactor-Essentials/blob/master/Essentials/UI/CooldownButton.cs) - Code for the cooldown button comes from **DorCoMaNdO**\ +[Essentials](https://github.com/DorCoMaNdO/Reactor-Essentials) - Custom game options by **DorCoMaNdO**: +- Before v1.6: We used the default Essentials release +- v1.6-v1.8: We slightly changed the default Essentials. The changes can be found on this [branch](https://github.com/Eisbison/Reactor-Essentials/tree/feature/TheOtherRoles-Adaption) of our fork. +- v2.0.0 and later: As we're not using Reactor anymore, we are using our own implementation, inspired by the one from **DorCoMaNdO** + [Jackal and Sidekick](https://www.twitch.tv/dhalucard) - Original idea for the Jackal and Sidekick comes from **Dhalucard**\ [Among-Us-Love-Couple-Mod](https://github.com/Woodi-dev/Among-Us-Love-Couple-Mod) - Idea for the Lovers role comes from **Woodi-dev**\ [Jester](https://github.com/Maartii/Jester) - Idea for the Jester role comes from **Maartii**\ @@ -146,6 +180,12 @@ the *.dll* file into your Among Us/BepInEx/plugins folder and you're good to go. [TownOfUs](https://github.com/slushiegoose/Town-Of-Us) - Idea for the Swapper, Shifter and a similar Mayor role come from **Slushiegoose**\ [Ottomated](https://twitter.com/ottomated_) - Idea for the Morphling, Snitch and Camouflager role come from **Ottomated** +# Settings +The mod adds a few new settings to Among Us (in addition to the role settings): +- The number of Impostor count be set inside a lobby +- The map can be changed inside a lobby +- 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) + # Roles ## Role Assignment @@ -158,9 +198,9 @@ The count you set will only be reached, if there are enough Crewmates/Impostors - After that each role that has 10%-90% selected adds 1-9 tickets to a ticket pool (one pool for Impostors, one for Crewmates). Then the roles will be selected randomly from that pool as long as possible (until the selected number is reached, until there are no more crewmates or until there are no more tickets). If a role is selected from the pool, obviously all the tickets of that role are being removed. **Example:**\ -Settings: 2 special crewmate roles, Snitch: 100%, Spy: 10%, Tracker: 30%\ -Result: Snitch is assigned, then one role out of the pool [Spy, Tracker, Tracker, Tracker] is being selected\ -Note: Changing the settings to Spy: 20%, Tracker: 60% would statistically result in the same outcome . +Settings: 2 special crewmate roles, Snitch: 100%, Hacker: 10%, Tracker: 30%\ +Result: Snitch is assigned, then one role out of the pool [Hacker, Tracker, Tracker, Tracker] is being selected\ +Note: Changing the settings to Hacker: 20%, Tracker: 60% would statistically result in the same outcome . ## Mafia @@ -170,7 +210,7 @@ The Godfather works like a normal Impostor.\ The Mafioso is an impostor who cannot kill nor sabotage until the Godfather is dead.\ The Janitor is an impostor who cannot kill nor sabotage, but they can hide dead bodies instead.\ \ -**NOTE** +**NOTE:** - There have to be 3 impostors activated for the mafia to spawn. ### Game Options @@ -184,11 +224,13 @@ The Janitor is an impostor who cannot kill nor sabotage, but they can hide dead ### **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. \ -**NOTE** +**NOTE:** - They shrink to the size of the child when they copies its look. -- The color of the footprints does **not** change. -- The Seer still sees the Morphlings role if they revealed it. +- The Spy sees their new color on the admin table. +- The color of the footprints changes accordingly (also the ones that were already on the ground). - The other impostor still sees that they are an impostor (the name remains red). +- The shield indicator changes accordingly (the Morphling gains or loses the shield indicator) +- Tracker and Snitch arrows keep working. ### Game Options | Name | Description | @@ -201,12 +243,14 @@ The Morphling is an impostor which can additionally scan the appearance of a pla ### **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 -are hidden and all players have the same color. +are hidden and all players have the same color.\ \ **NOTE** -- The Child and Morphling when copying the child remain small. -- The color of the footprints does **not** change. -- The Seer still sees all the roles they revealed. +- The Child (and Morphling when copying the child) remains small and show its age. +- The color of the footprints turns gray (also the ones that were already on the ground). +- The Spy sees gray icons on the admin table +- The shield is not visible anymore +- Tracker and Snitch arrows keep working ### Game Options | Name | Description | @@ -219,9 +263,9 @@ are hidden and all players have the same color. ### **Team: Impostors** The Vampire is an impostor, that can bite other player. Bitten players die after a configurable amount of time.\ If the Vampire spawn chance is greater 0 (even if there is no Vampire in the game), all players can place one garlic.\ -If a victim is near a garlic, the "Bite Button" turns into the default "Kill Button" and the Vampire can only perform a normal kill. +If a victim is near a garlic, the "Bite Button" turns into the default "Kill Button" and the Vampire can only perform a normal kill.\ \ -**NOTE** +**NOTE:** - If a bitten player is still alive when a meeting is being called, he dies at the start of the meeting. - The cooldown is the same as the default kill cooldown (+ the kill delay if the Vampire bites the target). @@ -234,6 +278,27 @@ If a victim is near a garlic, the "Bite Button" turns into the default "Kill But | Vampire Can Kill Near Garlics | The Vampire can never bite when his victim is near a garlic. If this option is set to true, he can still perform a normal kill there. ----------------------- +## Eraser +### **Team: Impostors** +The Eraser is an Impostor that can erase the role of every player that is not an Impostor.\ +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 his target die before the next meeting.\ +\ +**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 his target, depending on who the Eraser erased) +- Erasing a Lover automatically erases the other Lover as well (if the second Lover is an ImpLover, he will turn into an Impostor) +- Erasing a Jackal that has a Sidekick, triggers the Sidekick promotion if it's activated in the settings +- As the erasing is being triggered before the eject of a player, erasing and voting out a Lover in the same round, would result in the +ex lover surviving as the partnership was erased before. Also a Jester win would not happen, as the erase will be triggered before. + +### Game Options +| Name | Description | +|----------|:-------------:| +| Eraser Spawn Chance | - +| Eraser Cooldown | The Erasers cooldown will increase by 10 seconds after every erase. +----------------------- + ## Lovers ### **Team: Either Crewmates or Impostors** There are always two lovers which are linked together.\ @@ -243,11 +308,11 @@ 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 among the last 3 players, however they can also win with their respective role.\ If both Lovers are crewmates, they can achieve a "double victory" but the crewmates then also win.\ -If one Lover is an impostor and one a crewmate, they can get a "Lovers solo win" where only they win (even if there is another impostor alive). +If one Lover is an impostor and one a crewmate, they can get a "Lovers solo win" where only they win (even if there is another impostor alive).\ \ -**NOTE** +**NOTE:** - If there is an equal amount of impostors and crewmates left in the game and one of the Lovers is an impostor, 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 exchanges role with one of the Lovers +- The Lovers can change if the Shifter takes the role of a Lovers ### Game Options | Name | Description | @@ -264,8 +329,8 @@ The Sheriff has the ability to kill impostors. If they try to kill a crewmate, they die instead. **NOTE** -- For now the Shifter won't die to the Sheriff (an option will be added in the next version). - If the Sheriff shoots the person the Medic shielded, the Sheriff and the shielded person **both remain unharmed**. +- If the Sheriff shoots a Child Impostor, the Sheriff dies if the Child is still growing up. If it's 18, the Child Impostor dies. ### Game Options | Name | Description | @@ -287,29 +352,16 @@ The Jester does not have any tasks. They win the game as a solo, if they get vot ## Seer ### **Team: Crewmates** -The Seer has the ability to find out about people's intentions. The information is only visible to them.\ -Depending on the selected option they either directly see the role of the player (appended to their name) or if the player is -a good (name text changes to yellow) or a bad (name text changes to a darker color) player.\ -Depending on the selected option the player will get a blue flash on their screen if they are being revealed by the Seer. -The Seer can make mistakes (how many depends on the selected option). If a mistake happens, the information of another player (not the target, not the Seer) gets revealed. - -\ -**NOTE** -- **Good players:** Crewmates with all their special roles -- **Bad players:** Impostors with all their special roles (Mafia, Morphling, Camouflager, ImpLover), the neutral roles (Jester, Shifter) and the team Jackal. -- **Cooldown:** The cooldown of the Seer wil **not** be reset after a meeting (in order to balance the option to reveal roles) -- If the role of a revealed player changes during the game (because of e.g. the Shifter), the information of the Seers also adapts. -- When the Camouflager camouflages all players or the Morphling copies the appearance of another player, the Seer still sees the information they gained earlier (i.e. they still see that the player is the Morphling even if their appearance is different). -- If the Shifter exchanges the role with the Seer, the information gained by the Seer will be transfered to the new Seer (i.e. the new Seer sees what the old one revealed and the old one "loses" the information they gained). +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 slowy fade away. +The Seer gets a blue flash on his screen, if a player dies somewhere on the map. ### Game Options -| Name | Description | Options | -|----------|:-------------:|:-------------:| -| Seer Spawn Chance | - | - -| Seer Cooldown | Cooldown for his special ability. This cooldown will **not** be reset after a meeting | - -| Seer Chance Of Seeing Right | Sets the chance of how likely the Seer makes a mistake | - -| Info That Seer Reveals | Description above | "Role", "Good/Bad" -| Players That See When They Are Being Revealed | Selects the group of players that get notified when they are being revealed | "Everyone", "The Good", "The Bad", "Nobody" +| Name | Description | +|----------|:-------------:| +| Seer Spawn Chance | - +| Seer Mode | Options: Show death flash and souls, show death flash, show souls +| Seer Soul Duration | Sets how long it will take the souls to turn invisible after a meeting ----------------------- ## Engineer @@ -320,7 +372,7 @@ 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** +**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. ### Game Options @@ -332,10 +384,12 @@ you can double click on the tasks instead. ## 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 recieve 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** -- Even when the Morphling changes their appearance or the Camouflager camouflages everyone, the -Detective still sees the right (original) colors. +- **Lighter Colors:** Pink, orange, yellow, white, cyan, lime +- **Darker Colors:** Red, blue, green, grey, purple, brown +- 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 ### Game Options @@ -345,30 +399,40 @@ Detective still sees the right (original) colors. | Anonymous Footprints | If set to true, all footprints will have the same color. Otherwise they will have the color of the respective player. | Footprint Intervall | The intervall 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. | ----------------------- ## Lighter ### **Team: Crewmates** -The vision of the Lighter never changes, even if the lights are out.\ -Depending on the options the Lighter can have a bigger or smaller vision than other crewmates. +The Lighter can turn on his lighter every now and then, which increases his vision by a costumizable amount. ### Game Options | Name | Description | |----------|:-------------:| | Lighter Spawn Chance | - -| Lighter Vision | - +| Lighter Mode Vision On Lights On | The vision the Lighter has when the lights are on and the Lighter mode is on +| Lighter Mode Vision On Lights Off | The vision the Lighter has when the lights are down and the Lighter mode is on +| Lighter Cooldown | - +| Lighter Duration | - ----------------------- ## Child -### **Team: Crewmates** -The Child won't be harmed by anyone until it turns 18 years old, then it becomes a regular crewmate.\ +### **Team: Crewmates or Impostors** +The Child can be a Crewmate (67% chance) or an Impostor (33% chance).\ The Child's character is smaller and hence visible to everyone in the game.\ -The child works with the crewmates and aims to play out the strength of its "invincibility" in the early game.\ -If the child is voted out before it turns 18, everyone in the lobby loses. -\ -**NOTE** -- Impostors can't kill the child (the button does not work) until it turns 18 -- The Sheriff always suicides if he tries to kill the child +The Child cannot be killed until it turns 18 years old, however it can be voted out.\ +**Impostor Child:** + - While growing up the kill cooldown is doubled. When it's fully grown up its kill cooldown is 2/3 of the default one. + - If it gets thrown out of the ship, everything is fine. + +**Crewmate Child:** + - The Crewmate Child aims to play out the strength its invincibility in the early game. + - If it gets thrown out of the ship before it turns 18, everyone loses. So think twice before you vote out a Child. + +**NOTE:** +- Impostors can't kill the Child (the button does not work) until it turns 18 +- The Sheriff can kill the Impostor Child, but only if it's fully grown up ### Game Options | Name | Description | @@ -384,11 +448,9 @@ The shielded player can still be voted out and might also be an impostor.\ If set in the options, the shielded player 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.\ -The Medic's other feature shows when they report a corpse: they recieve 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 Medic's other feature shows when they report a corpse: they will see how long ago the player died \ **NOTE** -- **Lighter Colors:** Pink, orange, yellow, white, cyan, lime -- **Darker Colors:** Red, blue, green, grey, purple, brown - 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. @@ -398,14 +460,13 @@ The Medic's other feature shows when they report a corpse: they recieve clues ab |----------|:-------------:|:-------------:| | Medic Spawn Chance | - | - | Show Shielded Player | Sets who sees if a player has a shield | "Everyone", "Shielded + Medic", "Medic" -| Time Where Medic Reports Will Have Name | The amount of time that the Medic will have to report the body since death to get the killer's name. | -| Time Where Medic Reports Will Have Color Type| The amount of time that the Medic will have to report the body since death to get the killer's color type. | -|Shielded Player Sees Murder Attempt| Whether a shielded player sees if someone tries to kill him | True/false | +| Shielded Player Sees Murder Attempt| Whether a shielded player sees if someone tries to kill him | True/false | ----------------------- ## Mayor ### **Team: Crewmates** -The Mayor leades the crewmates by having a vote that counts twice. +The Mayor leades the crewmates by having a vote that counts twice.\ +The Mayor can always use his meeting, even if the maximum number of meetings was reached. ### Game Options | Name | Description | @@ -413,49 +474,65 @@ The Mayor leades the crewmates by having a vote that counts twice. | Mayor Spawn Chance | - ----------------------- -## Spy +## Hacker ### **Team: Crewmates** -If the Spy activates the "Spy mode", the Spy gets more information than others from the admin table and vitals for a set duration.\ +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 he sees the same information as everyone else. -**Admin table:** The spy can see the colors of the players on the table.\ -**Vitals**: The spy can see how long dead players have been dead for.\ +**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.\ \ **NOTE:** -- Even if the Morphling morphes or the Camouflager camouflages, the Spy sees the right colors on the admin table. +- If the Morphling morphes or the Camouflager camouflages, the colors on the admin table change accordingly +- **Lighter Colors:** Pink, orange, yellow, white, cyan, lime +- **Darker Colors:** Red, blue, green, grey, purple, brown + ### Game Options | Name | Description | |----------|:-------------:| -| Spy Spawn Chance | - -| Spy Cooldown| - -| Spy Duration | Sets how long the "Spy mode" remains active +| Hacker Spawn Chance | - +| Hacker Cooldown| - +| Hacker Duration | Sets how long the "Hacker mode" remains active +| Hacker Only Sees Color Type | Sets if the Hacker sees the player colors on the admin table or only white/gray (for lighter and darker colors) ----------------------- ## Shifter -### **Team: Neutral** -The Shifter belongs to no team and has no tasks.\ -The Shifter always loses the game, however they can exchange roles with other players.\ -Swapping roles with a crewmate or a custom crewmate role (or the Jester) gives them their role and their tasks, the other player becomes the new Shifter.\ -Swapping roles with an impostor or a custom impostor role fails and the Shifter commits suicide.\ +### **Team: Crewmates** +The Shifter can take over the role of another Crewmate or Neutral, 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 a Crewmate or Neutral gives them their role, the other player becomes the new Shifter.\ +Swapping roles with an impostor or a custom impostor role fails and the Shifter commits suicide (there won't be a body after the meeting).\ +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 possiblity 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 his target, depending on who 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 player they exchanged roles with have not used them before) +can only use them, if the previous player did not used them before) ### Game Options | Name | Description |----------|:-------------:| | Shifter Spawn Chance | - -| Shifter Cooldown | - ----------------------- ## Time Master ### **Team: Crewmates** -The Time Master can rewind the time. The Time Master won't be affected by the rewind.\ -If set in the options, players will be revived during the time rewind.\ -Only movement and kills are affected (not cooldowns, meetings, tasks, ...) +The Time Master has a time shield which he can activate. The time shield remains active for 3 seconds.\ +If a player trys 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 movement and kills are affected (not cooldowns, meetings, tasks, ...) +- A Vampire bite will trigger the rewind. If the Time Master misses shielding the bite, he can still shield the kill which happens a few seconds later. +- If the Time Master was bitten and has his shield active before when a meeting is called, he survives but the time won't be rewinded. +- If the Time Master has a Medic shield, he won't rewind. ### Game Options | Name | Description | @@ -463,7 +540,6 @@ Only movement and kills are affected (not cooldowns, meetings, tasks, ...) | Time Master Spawn Chance | - | | Time Master Cooldown | - | | Rewind Duration | How much time to rewind | -| Revive During Rewind | Whether to revive dead players when rewinding | ----------------------- ## Swapper @@ -494,7 +570,7 @@ The arrow updates it's position every few seconds (configurable). ## Snitch ### **Team: Crewmates** -When the Snitch finshes all the tasks, arrows will appear (only visible to the Snitch) that point to the impostors. +When the Snitch finishes all the tasks, arrows will appear (only visible to the Snitch) that point to the impostors. When the Snitch has one task left (configurable) the Snitch will be revealed to the impostors, also with an arrow. ### Game Options @@ -568,7 +644,7 @@ Upon the death of the Jackal (depending on the options), he might get promoted t # 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. -You can use parts of the codes but don't copy paste the whole thing. Make sure you give credits to the other developers, because some parts of the code are base on theirs. And yes it is in a zip file... I will change that. +You can use parts of the codes but don't copy paste the whole thing. Make sure you give credits to the other developers, because some parts of the code are based on theirs. # Bugs, suggestions and requests If you found any bugs, have an idea for an idea for a new role or any other request, join my [Discord server](https://discord.gg/77RkMJHWsM) \ No newline at end of file diff --git a/Source Code/Arrow.cs b/Source Code/Arrow.cs index a4d0360..946e0ff 100644 --- a/Source Code/Arrow.cs +++ b/Source Code/Arrow.cs @@ -2,9 +2,8 @@ using System; using System.Collections.Generic; using System.Collections; using UnityEngine; -using static TheOtherRoles.TheOtherRoles; -namespace TheOtherRoles{ +namespace TheOtherRoles { public class Arrow { public float perc = 0.925f; public SpriteRenderer image; diff --git a/Source Code/Buttons.cs b/Source Code/Buttons.cs index 6318128..c442615 100644 --- a/Source Code/Buttons.cs +++ b/Source Code/Buttons.cs @@ -1,14 +1,15 @@ using HarmonyLib; using Hazel; using System; -using System.IO; -using System.Net.Http; using UnityEngine; using static TheOtherRoles.TheOtherRoles; -using Reactor.Extensions; -using System.Collections.Generic; -using System.Linq; -using UnhollowerBaseLib; + +using Palette = GLNPIJPGGNJ; +using TaskTypes = CBFIAGIGOFA; +using SystemTypes = LGBKLKNAINN; +using Constants = NFONDPLFBCP; +using PhysicsHelpers = IEPBCHBGDOA; +using Effects = HLPCBNMDEHF; namespace TheOtherRoles { @@ -18,40 +19,44 @@ namespace TheOtherRoles private static CustomButton engineerRepairButton; private static CustomButton janitorCleanButton; private static CustomButton sheriffKillButton; - private static CustomButton timeMasterRewindTimeButton; + private static CustomButton timeMasterShieldButton; private static CustomButton medicShieldButton; private static CustomButton shifterShiftButton; - private static CustomButton seerRevealButton; private static CustomButton morphlingButton; private static CustomButton camouflagerButton; - private static CustomButton spyButton; + private static CustomButton hackerButton; private static CustomButton trackerButton; private static CustomButton vampireKillButton; private static CustomButton garlicButton; private static CustomButton jackalKillButton; private static CustomButton sidekickKillButton; private static CustomButton jackalSidekickButton; + private static CustomButton lighterButton; + private static CustomButton eraserButton; public static void setCustomButtonCooldowns() { engineerRepairButton.MaxTimer = 0f; janitorCleanButton.MaxTimer = Janitor.cooldown; sheriffKillButton.MaxTimer = Sheriff.cooldown; - timeMasterRewindTimeButton.MaxTimer = TimeMaster.cooldown; + timeMasterShieldButton.MaxTimer = TimeMaster.cooldown; medicShieldButton.MaxTimer = 0f; - shifterShiftButton.MaxTimer = Shifter.cooldown; - seerRevealButton.MaxTimer = Seer.cooldown; + shifterShiftButton.MaxTimer = 0f; morphlingButton.MaxTimer = Morphling.cooldown; camouflagerButton.MaxTimer = Camouflager.cooldown; - spyButton.MaxTimer = Spy.cooldown; + hackerButton.MaxTimer = Hacker.cooldown; vampireKillButton.MaxTimer = Vampire.cooldown; trackerButton.MaxTimer = 0f; garlicButton.MaxTimer = 0f; jackalKillButton.MaxTimer = Jackal.cooldown; sidekickKillButton.MaxTimer = Sidekick.cooldown; jackalSidekickButton.MaxTimer = Jackal.createSidekickCooldown; + lighterButton.MaxTimer = Lighter.cooldown; + eraserButton.MaxTimer = Eraser.cooldown; - spyButton.EffectDuration = Spy.duration; - vampireKillButton.EffectDuration= Vampire.delay; + timeMasterShieldButton.EffectDuration = TimeMaster.shieldDuration; + hackerButton.EffectDuration = Hacker.duration; + vampireKillButton.EffectDuration = Vampire.delay; + lighterButton.EffectDuration = Lighter.duration; } public static void Postfix(HudManager __instance) @@ -80,16 +85,19 @@ namespace TheOtherRoles } else if (task.TaskType == TaskTypes.FixComms) { ShipStatus.Instance.RpcRepairSystem(SystemTypes.Comms, 16 | 0); ShipStatus.Instance.RpcRepairSystem(SystemTypes.Comms, 16 | 1); + } else if (task.TaskType == TaskTypes.StopCharles) { + ShipStatus.Instance.RpcRepairSystem(SystemTypes.Reactor, 0 | 16); + ShipStatus.Instance.RpcRepairSystem(SystemTypes.Reactor, 1 | 16); } } }, - () => { return Engineer.engineer != null && Engineer.engineer == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.Data.IsDead; }, + () => { return Engineer.engineer != null && Engineer.engineer == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.IDOFAMCIJKE.FGNJJFABIHJ; }, () => { bool sabotageActive = false; foreach (PlayerTask task in PlayerControl.LocalPlayer.myTasks) - if (task.TaskType == TaskTypes.FixLights || task.TaskType == TaskTypes.RestoreOxy || task.TaskType == TaskTypes.ResetReactor || task.TaskType == TaskTypes.ResetSeismic || task.TaskType == TaskTypes.FixComms) + if (task.TaskType == TaskTypes.FixLights || task.TaskType == TaskTypes.RestoreOxy || task.TaskType == TaskTypes.ResetReactor || task.TaskType == TaskTypes.ResetSeismic || task.TaskType == TaskTypes.FixComms || task.TaskType == TaskTypes.StopCharles) sabotageActive = true; - return sabotageActive && !Engineer.usedRepair && PlayerControl.LocalPlayer.CanMove; + return sabotageActive && !Engineer.usedRepair && PlayerControl.LocalPlayer.AMDJMEEHNIG; }, () => {}, Engineer.getButtonSprite(), @@ -100,22 +108,22 @@ namespace TheOtherRoles // Janitor Clean janitorCleanButton = new CustomButton( () => { - foreach (Collider2D collider2D in Physics2D.OverlapCircleAll(PlayerControl.LocalPlayer.GetTruePosition(), PlayerControl.LocalPlayer.MaxReportDistance, Constants.PlayersOnlyMask)) { + foreach (Collider2D collider2D in Physics2D.OverlapCircleAll(PlayerControl.LocalPlayer.GetTruePosition(), PlayerControl.LocalPlayer.MaxReportDistance, Constants.NFGGONLDDAN)) { if (collider2D.tag == "DeadBody") { DeadBody component = collider2D.GetComponent(); if (component && !component.Reported) { Vector2 truePosition = PlayerControl.LocalPlayer.GetTruePosition(); - Vector2 truePosition2 = component.TruePosition; - if (Vector2.Distance(truePosition2, truePosition) <= PlayerControl.LocalPlayer.MaxReportDistance && PlayerControl.LocalPlayer.CanMove && !PhysicsHelpers.AnythingBetween(truePosition, truePosition2, Constants.ShipAndObjectsMask, false)) + Vector2 truePosition2 = component.NCMFGFMFDJB; + if (Vector2.Distance(truePosition2, truePosition) <= PlayerControl.LocalPlayer.MaxReportDistance && PlayerControl.LocalPlayer.AMDJMEEHNIG && !PhysicsHelpers.GCFCONMBBOF(truePosition, truePosition2, Constants.DHLPLBPJNBA, false)) { - GameData.PlayerInfo playerInfo = GameData.Instance.GetPlayerById(component.ParentId); + GameData.OFKOJOKOOAK OFKOJOKOOAK = GameData.Instance.GetPlayerById(component.ParentId); MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.JanitorClean, Hazel.SendOption.Reliable, -1); - writer.Write(playerInfo.PlayerId); + writer.Write(OFKOJOKOOAK.GMBAIPNOKLP); AmongUsClient.Instance.FinishRpcImmediately(writer); - RPCProcedure.janitorClean(playerInfo.PlayerId); + RPCProcedure.janitorClean(OFKOJOKOOAK.GMBAIPNOKLP); janitorCleanButton.Timer = janitorCleanButton.MaxTimer; break; @@ -124,8 +132,8 @@ namespace TheOtherRoles } } }, - () => { return Janitor.janitor != null && Janitor.janitor == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.Data.IsDead; }, - () => { return __instance.ReportButton.renderer.color == Palette.EnabledColor && PlayerControl.LocalPlayer.CanMove; }, + () => { return Janitor.janitor != null && Janitor.janitor == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.IDOFAMCIJKE.FGNJJFABIHJ; }, + () => { return __instance.ReportButton.renderer.color == Palette.MKAFGNEBHKC && PlayerControl.LocalPlayer.AMDJMEEHNIG; }, () => { janitorCleanButton.Timer = janitorCleanButton.MaxTimer;}, Janitor.getButtonSprite(), new Vector3(-1.3f, 0, 0), @@ -143,10 +151,11 @@ namespace TheOtherRoles } byte targetId = 0; - if (Sheriff.currentTarget.Data.IsImpostor || + if ((Sheriff.currentTarget.IDOFAMCIJKE.CIDDOFDJHJH && (Sheriff.currentTarget != Child.child || Child.isGrownUp())) || Sheriff.currentTarget == Jackal.jackal || Sheriff.currentTarget == Sidekick.sidekick || - (Sheriff.jesterCanDieToSheriff && Jester.jester != null && Jester.jester == Sheriff.currentTarget)) { + (Sheriff.jesterCanDieToSheriff && Jester.jester != null && Jester.jester == Sheriff.currentTarget)) + { targetId = Sheriff.currentTarget.PlayerId; } else { @@ -160,8 +169,8 @@ namespace TheOtherRoles sheriffKillButton.Timer = sheriffKillButton.MaxTimer; Sheriff.currentTarget = null; }, - () => { return Sheriff.sheriff != null && Sheriff.sheriff == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.Data.IsDead; }, - () => { return Sheriff.currentTarget && PlayerControl.LocalPlayer.CanMove; }, + () => { return Sheriff.sheriff != null && Sheriff.sheriff == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.IDOFAMCIJKE.FGNJJFABIHJ; }, + () => { return Sheriff.currentTarget && PlayerControl.LocalPlayer.AMDJMEEHNIG; }, () => { sheriffKillButton.Timer = sheriffKillButton.MaxTimer;}, __instance.KillButton.renderer.sprite, new Vector3(-1.3f, 0, 0), @@ -169,19 +178,25 @@ namespace TheOtherRoles ); // Time Master Rewind Time - timeMasterRewindTimeButton = new CustomButton( + timeMasterShieldButton = new CustomButton( () => { - MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.TimeMasterRewindTime, Hazel.SendOption.Reliable, -1); + MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.TimeMasterShield, Hazel.SendOption.Reliable, -1); AmongUsClient.Instance.FinishRpcImmediately(writer); - RPCProcedure.timeMasterRewindTime(); - timeMasterRewindTimeButton.Timer = timeMasterRewindTimeButton.MaxTimer; + RPCProcedure.timeMasterShield(); + }, + () => { return TimeMaster.timeMaster != null && TimeMaster.timeMaster == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.IDOFAMCIJKE.FGNJJFABIHJ; }, + () => { return PlayerControl.LocalPlayer.AMDJMEEHNIG; }, + () => { + timeMasterShieldButton.Timer = timeMasterShieldButton.MaxTimer; + timeMasterShieldButton.isEffectActive = false; + timeMasterShieldButton.killButtonManager.TimerText.Color = Palette.MKAFGNEBHKC; }, - () => { return TimeMaster.timeMaster != null && TimeMaster.timeMaster == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.Data.IsDead; }, - () => { return PlayerControl.LocalPlayer.CanMove; }, - () => { timeMasterRewindTimeButton.Timer = timeMasterRewindTimeButton.MaxTimer;}, TimeMaster.getButtonSprite(), new Vector3(-1.3f, 0, 0), - __instance + __instance, + true, + TimeMaster.shieldDuration, + () => { timeMasterShieldButton.Timer = timeMasterShieldButton.MaxTimer; } ); // Medic Shield @@ -194,8 +209,8 @@ namespace TheOtherRoles AmongUsClient.Instance.FinishRpcImmediately(writer); RPCProcedure.medicSetShielded(Medic.currentTarget.PlayerId); }, - () => { return Medic.medic != null && Medic.medic == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.Data.IsDead; }, - () => { return !Medic.usedShield && Medic.currentTarget && PlayerControl.LocalPlayer.CanMove; }, + () => { return Medic.medic != null && Medic.medic == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.IDOFAMCIJKE.FGNJJFABIHJ; }, + () => { return !Medic.usedShield && Medic.currentTarget && PlayerControl.LocalPlayer.AMDJMEEHNIG; }, () => {}, Medic.getButtonSprite(), new Vector3(-1.3f, 0, 0), @@ -206,52 +221,19 @@ namespace TheOtherRoles // Shifter shift shifterShiftButton = new CustomButton( () => { - shifterShiftButton.Timer = shifterShiftButton.MaxTimer; - - MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.ShifterShift, Hazel.SendOption.Reliable, -1); + MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.SetFutureShifted, Hazel.SendOption.Reliable, -1); writer.Write(Shifter.currentTarget.PlayerId); AmongUsClient.Instance.FinishRpcImmediately(writer); - - RPCProcedure.shifterShift(Shifter.currentTarget.PlayerId); + RPCProcedure.setFutureShifted(Shifter.currentTarget.PlayerId); }, - () => { return Shifter.shifter != null && Shifter.shifter == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.Data.IsDead; }, - () => { return Shifter.currentTarget && PlayerControl.LocalPlayer.CanMove; }, - () => { shifterShiftButton.Timer = shifterShiftButton.MaxTimer; }, + () => { return Shifter.shifter != null && Shifter.shifter == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.IDOFAMCIJKE.FGNJJFABIHJ; }, + () => { return Shifter.currentTarget && Shifter.futureShift == null && PlayerControl.LocalPlayer.AMDJMEEHNIG; }, + () => { }, Shifter.getButtonSprite(), new Vector3(-1.3f, 0, 0), __instance ); - // Seer reveal - seerRevealButton = new CustomButton( - () => { - seerRevealButton.Timer = seerRevealButton.MaxTimer; - - PlayerControl targetOrMistake = Seer.currentTarget; - if (rnd.Next(1, 101) > Seer.chanceOfSeeingRight) { - var players = PlayerControl.AllPlayerControls.ToArray().ToList(); - players.RemoveAll(p => p != null && (p.PlayerId == Seer.seer.PlayerId || p.PlayerId == Seer.currentTarget.PlayerId)); - int index = rnd.Next(0, players.Count); - - if (players.Count != 0 && players[index] != null) - targetOrMistake = players[index]; - } - - MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.SeerReveal, Hazel.SendOption.Reliable, -1); - writer.Write(Seer.currentTarget.PlayerId); - writer.Write(targetOrMistake.PlayerId); - AmongUsClient.Instance.FinishRpcImmediately(writer); - - RPCProcedure.seerReveal(Seer.currentTarget.PlayerId, targetOrMistake.PlayerId); - }, - () => { return Seer.seer != null && Seer.seer == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.Data.IsDead; }, - () => { return Seer.currentTarget && PlayerControl.LocalPlayer.CanMove; }, - () => {}, - Seer.getButtonSprite(), - new Vector3(-1.3f, 0, 0), - __instance - ); - // Morphling morph morphlingButton = new CustomButton( () => { @@ -268,13 +250,13 @@ namespace TheOtherRoles morphlingButton.HasEffect = false; // Block effect on this click } }, - () => { return Morphling.morphling != null && Morphling.morphling == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.Data.IsDead; }, - () => { return (Morphling.currentTarget || Morphling.sampledTarget) && PlayerControl.LocalPlayer.CanMove; }, + () => { return Morphling.morphling != null && Morphling.morphling == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.IDOFAMCIJKE.FGNJJFABIHJ; }, + () => { return (Morphling.currentTarget || Morphling.sampledTarget) && PlayerControl.LocalPlayer.AMDJMEEHNIG; }, () => { morphlingButton.Timer = morphlingButton.MaxTimer; morphlingButton.Sprite = Morphling.getSampleSprite(); morphlingButton.isEffectActive = false; - morphlingButton.killButtonManager.TimerText.Color = Palette.EnabledColor; + morphlingButton.killButtonManager.TimerText.Color = Palette.MKAFGNEBHKC; Morphling.sampledTarget = null; }, Morphling.getSampleSprite(), @@ -295,12 +277,12 @@ namespace TheOtherRoles AmongUsClient.Instance.FinishRpcImmediately(writer); RPCProcedure.camouflagerCamouflage(); }, - () => { return Camouflager.camouflager != null && Camouflager.camouflager == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.Data.IsDead; }, - () => { return PlayerControl.LocalPlayer.CanMove; }, + () => { return Camouflager.camouflager != null && Camouflager.camouflager == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.IDOFAMCIJKE.FGNJJFABIHJ; }, + () => { return PlayerControl.LocalPlayer.AMDJMEEHNIG; }, () => { camouflagerButton.Timer = camouflagerButton.MaxTimer; camouflagerButton.isEffectActive = false; - camouflagerButton.killButtonManager.TimerText.Color = Palette.EnabledColor; + camouflagerButton.killButtonManager.TimerText.Color = Palette.MKAFGNEBHKC; }, Camouflager.getButtonSprite(), new Vector3(-1.3f, 1.3f, 0f), @@ -310,25 +292,25 @@ namespace TheOtherRoles () => { camouflagerButton.Timer = camouflagerButton.MaxTimer; } ); - // Spy button - spyButton = new CustomButton( + // Hacker button + hackerButton = new CustomButton( () => { - Spy.spyTimer = Spy.duration; + Hacker.hackerTimer = Hacker.duration; }, - () => { return Spy.spy != null && Spy.spy == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.Data.IsDead; }, - () => { return PlayerControl.LocalPlayer.CanMove; }, + () => { return Hacker.hacker != null && Hacker.hacker == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.IDOFAMCIJKE.FGNJJFABIHJ; }, + () => { return PlayerControl.LocalPlayer.AMDJMEEHNIG; }, () => { - spyButton.Timer = spyButton.MaxTimer; - spyButton.isEffectActive = false; - spyButton.killButtonManager.TimerText.Color = Palette.EnabledColor; + hackerButton.Timer = hackerButton.MaxTimer; + hackerButton.isEffectActive = false; + hackerButton.killButtonManager.TimerText.Color = Palette.MKAFGNEBHKC; }, - Spy.getButtonSprite(), + Hacker.getButtonSprite(), new Vector3(-1.3f, 0, 0), __instance, true, 0f, () => { - spyButton.Timer = spyButton.MaxTimer; + hackerButton.Timer = hackerButton.MaxTimer; } ); @@ -340,8 +322,8 @@ namespace TheOtherRoles AmongUsClient.Instance.FinishRpcImmediately(writer); RPCProcedure.trackerUsedTracker(Tracker.currentTarget.PlayerId); }, - () => { return Tracker.tracker != null && Tracker.tracker == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.Data.IsDead; }, - () => { return PlayerControl.LocalPlayer.CanMove && Tracker.currentTarget != null && !Tracker.usedTracker; }, + () => { return Tracker.tracker != null && Tracker.tracker == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.IDOFAMCIJKE.FGNJJFABIHJ; }, + () => { return PlayerControl.LocalPlayer.AMDJMEEHNIG && Tracker.currentTarget != null && !Tracker.usedTracker; }, () => { }, Tracker.getButtonSprite(), new Vector3(-1.3f, 0, 0), @@ -357,29 +339,49 @@ namespace TheOtherRoles vampireKillButton.Timer = vampireKillButton.MaxTimer; } else { Vampire.bitten = Vampire.currentTarget; - Reactor.Coroutines.Start(Vampire.killWithDelay()); - MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.VampireBiteNotification, Hazel.SendOption.Reliable, -1); + // Notify players about bitten + MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.VampireSetBitten, Hazel.SendOption.Reliable, -1); writer.Write(Vampire.bitten.PlayerId); + writer.Write(0); AmongUsClient.Instance.FinishRpcImmediately(writer); - RPCProcedure.vampireBiteNotification(Vampire.bitten.PlayerId); + RPCProcedure.vampireSetBitten(Vampire.bitten.PlayerId, 0); + + PlayerControl.LocalPlayer.StartCoroutine(Effects.LDACHPMFOIF(Vampire.delay, new Action((p) => { // Delayed action + if (p == 1f) { + if (Vampire.bitten != null && !Vampire.bitten.IDOFAMCIJKE.FGNJJFABIHJ && Helpers.handleMurderAttempt(Vampire.bitten)) { + // Perform kill + MessageWriter killWriter = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.VampireTryKill, Hazel.SendOption.Reliable, -1); + AmongUsClient.Instance.FinishRpcImmediately(killWriter); + RPCProcedure.vampireTryKill(); + } else { + // Notify players about clearing bitten + MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.VampireSetBitten, Hazel.SendOption.Reliable, -1); + writer.Write(byte.MaxValue); + writer.Write(byte.MaxValue); + AmongUsClient.Instance.FinishRpcImmediately(writer); + RPCProcedure.vampireSetBitten(byte.MaxValue, byte.MaxValue); + } + } + }))); + vampireKillButton.HasEffect = true; // Trigger effect on this click } } else { vampireKillButton.HasEffect = false; // Block effect if no action was fired } }, - () => { return Vampire.vampire != null && Vampire.vampire == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.Data.IsDead; }, + () => { return Vampire.vampire != null && Vampire.vampire == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.IDOFAMCIJKE.FGNJJFABIHJ; }, () => { if (Vampire.targetNearGarlic && Vampire.canKillNearGarlics) vampireKillButton.killButtonManager.renderer.sprite = __instance.KillButton.renderer.sprite; else vampireKillButton.killButtonManager.renderer.sprite = Vampire.getButtonSprite(); - return Vampire.currentTarget != null && PlayerControl.LocalPlayer.CanMove && (!Vampire.targetNearGarlic || Vampire.canKillNearGarlics); + return Vampire.currentTarget != null && PlayerControl.LocalPlayer.AMDJMEEHNIG && (!Vampire.targetNearGarlic || Vampire.canKillNearGarlics); }, () => { vampireKillButton.Timer = vampireKillButton.MaxTimer; vampireKillButton.isEffectActive = false; - vampireKillButton.killButtonManager.TimerText.Color = Palette.EnabledColor; + vampireKillButton.killButtonManager.TimerText.Color = Palette.MKAFGNEBHKC; }, Vampire.getButtonSprite(), new Vector3(-1.3f, 0, 0), @@ -404,8 +406,8 @@ namespace TheOtherRoles writer.EndMessage(); RPCProcedure.placeGarlic(buff); }, - () => { return !Vampire.localPlacedGarlic && !PlayerControl.LocalPlayer.Data.IsDead && Vampire.garlicsActive; }, - () => { return PlayerControl.LocalPlayer.CanMove && !Vampire.localPlacedGarlic; }, + () => { return !Vampire.localPlacedGarlic && !PlayerControl.LocalPlayer.IDOFAMCIJKE.FGNJJFABIHJ && Vampire.garlicsActive; }, + () => { return PlayerControl.LocalPlayer.AMDJMEEHNIG && !Vampire.localPlacedGarlic; }, () => { }, Vampire.getGarlicButtonSprite(), Vector3.zero, @@ -422,8 +424,8 @@ namespace TheOtherRoles AmongUsClient.Instance.FinishRpcImmediately(writer); RPCProcedure.jackalCreatesSidekick(Jackal.currentTarget.PlayerId); }, - () => { return Jackal.canCreateSidekick && Sidekick.sidekick == null && Jackal.fakeSidekick == null && Jackal.jackal != null && Jackal.jackal == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.Data.IsDead; }, - () => { return Sidekick.sidekick == null && Jackal.fakeSidekick == null && Jackal.currentTarget != null && PlayerControl.LocalPlayer.CanMove; }, + () => { return Jackal.canCreateSidekick && Sidekick.sidekick == null && Jackal.fakeSidekick == null && Jackal.jackal != null && Jackal.jackal == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.IDOFAMCIJKE.FGNJJFABIHJ; }, + () => { return Sidekick.sidekick == null && Jackal.fakeSidekick == null && Jackal.currentTarget != null && PlayerControl.LocalPlayer.AMDJMEEHNIG; }, () => { jackalSidekickButton.Timer = jackalSidekickButton.MaxTimer;}, Jackal.getSidekickButtonSprite(), new Vector3(-1.3f, 1.3f, 0f), @@ -442,8 +444,8 @@ namespace TheOtherRoles jackalKillButton.Timer = jackalKillButton.MaxTimer; Jackal.currentTarget = null; }, - () => { return Jackal.jackal != null && Jackal.jackal == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.Data.IsDead; }, - () => { return Jackal.currentTarget && PlayerControl.LocalPlayer.CanMove; }, + () => { return Jackal.jackal != null && Jackal.jackal == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.IDOFAMCIJKE.FGNJJFABIHJ; }, + () => { return Jackal.currentTarget && PlayerControl.LocalPlayer.AMDJMEEHNIG; }, () => { jackalKillButton.Timer = jackalKillButton.MaxTimer;}, __instance.KillButton.renderer.sprite, new Vector3(-1.3f, 0, 0), @@ -463,13 +465,53 @@ namespace TheOtherRoles sidekickKillButton.Timer = sidekickKillButton.MaxTimer; Sidekick.currentTarget = null; }, - () => { return Sidekick.canKill && Sidekick.sidekick != null && Sidekick.sidekick == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.Data.IsDead; }, - () => { return Sidekick.currentTarget && PlayerControl.LocalPlayer.CanMove; }, + () => { return Sidekick.canKill && Sidekick.sidekick != null && Sidekick.sidekick == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.IDOFAMCIJKE.FGNJJFABIHJ; }, + () => { return Sidekick.currentTarget && PlayerControl.LocalPlayer.AMDJMEEHNIG; }, () => { sidekickKillButton.Timer = sidekickKillButton.MaxTimer;}, __instance.KillButton.renderer.sprite, new Vector3(-1.3f, 0, 0), __instance ); + + // Lighter light + lighterButton = new CustomButton( + () => { + Lighter.lighterTimer = Lighter.duration; + }, + () => { return Lighter.lighter != null && Lighter.lighter == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.IDOFAMCIJKE.FGNJJFABIHJ; }, + () => { return PlayerControl.LocalPlayer.AMDJMEEHNIG; }, + () => { + lighterButton.Timer = lighterButton.MaxTimer; + lighterButton.isEffectActive = false; + lighterButton.killButtonManager.TimerText.Color = Palette.MKAFGNEBHKC; + }, + Lighter.getButtonSprite(), + new Vector3(-1.3f, 0f, 0f), + __instance, + true, + Lighter.duration, + () => { lighterButton.Timer = lighterButton.MaxTimer; } + ); + + // Eraser erase button + eraserButton = new CustomButton( + () => { + eraserButton.MaxTimer += 10; + eraserButton.Timer = eraserButton.MaxTimer; + + MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.SetFutureErased, Hazel.SendOption.Reliable, -1); + writer.Write(Eraser.currentTarget.PlayerId); + AmongUsClient.Instance.FinishRpcImmediately(writer); + RPCProcedure.setFutureErased(Eraser.currentTarget.PlayerId); + }, + () => { return Eraser.eraser != null && Eraser.eraser == PlayerControl.LocalPlayer && !PlayerControl.LocalPlayer.IDOFAMCIJKE.FGNJJFABIHJ; }, + () => { return PlayerControl.LocalPlayer.AMDJMEEHNIG && Eraser.currentTarget != null; }, + () => { eraserButton.Timer = eraserButton.MaxTimer;}, + Eraser.getButtonSprite(), + new Vector3(-1.3f, 1.3f, 0f), + __instance + ); + } } } \ No newline at end of file diff --git a/Source Code/CredentialsPatch.cs b/Source Code/CredentialsPatch.cs index 4fec516..1cb48b2 100644 --- a/Source Code/CredentialsPatch.cs +++ b/Source Code/CredentialsPatch.cs @@ -7,26 +7,32 @@ using System.Threading.Tasks; namespace TheOtherRoles { - [HarmonyPatch(typeof(VersionShower), nameof(VersionShower.Start))] - public static class VersionShowerPatch - { - static void Postfix(VersionShower __instance) { - string spacer = new String('\n', 15); - string text = "[FCCE03FF]TheOtherRoles[] v1.8.2:\n- Modded by [FCCE03FF]Eisbison[] and [FFEB91FF]Thunderstorm584[]\n- Balanced with [FFEB91FF]Dhalucard"; - if (__instance.text.Text.Contains(spacer)) - __instance.text.Text += "\n" + text; - else - __instance.text.Text += spacer + text; + [HarmonyPatch] + public static class CredentialsPatch { + [HarmonyPatch(typeof(VersionShower), nameof(VersionShower.Start))] + + private static class VersionShowerPatch + { + static void Postfix(VersionShower __instance) { + string spacer = new String('\n', 21); + string fullCredentials = "[FCCE03FF]TheOtherRoles[] v2.0.0 beta:\n- Modded by [FCCE03FF]Eisbison[] and [FFEB91FF]Thunderstorm584[]\n- Balanced with [FFEB91FF]Dhalucard[]\n- Button design by [FFEB91FF]Bavari[]"; + if (__instance.text.Text.Contains(spacer)) + __instance.text.Text += "\n" + fullCredentials; + else + __instance.text.Text += spacer + fullCredentials; + } } - } - [HarmonyPatch(typeof(PingTracker), nameof(PingTracker.Update))] - public static class PingTrackerPatch - { - static void Postfix(VersionShower __instance) + [HarmonyPatch(typeof(PingTracker), nameof(PingTracker.Update))] + private static class PingTrackerPatch { - __instance.text.Text += "\n[FCCE03FF]TheOtherRoles[FFFFFFFF]"; - __instance.text.Text += "\nModded by [FCCE03FF]Eisbison[FFFFFFFF]"; + static void Postfix(VersionShower __instance) + { + if (AmongUsClient.Instance.GameState == InnerNet.InnerNetClient.CJDCOJJNIGL.Started) + __instance.text.Text += "\n[FCCE03FF]TheOtherRoles[]\nModded by [FCCE03FF]Eisbison[]"; + else + __instance.text.Text += "\n\n[FCCE03FF]TheOtherRoles[]\nModded by [FCCE03FF]Eisbison[]\nand [FFEB91FF]Thunderstorm584[]\nBalanced with [FFEB91FF]Dhalucard[]\nButton design by [FFEB91FF]Bavari[]"; + } } } } diff --git a/Source Code/CustomButton.cs b/Source Code/CustomButton.cs index 65f9af8..ec672f1 100644 --- a/Source Code/CustomButton.cs +++ b/Source Code/CustomButton.cs @@ -2,10 +2,10 @@ using System; using System.Collections.Generic; using System.IO; using System.Reflection; -using Reactor.Extensions; -using Reactor.Unstrip; using UnityEngine; +using Palette = GLNPIJPGGNJ; + public class CustomButton { public static List buttons = new List(); @@ -68,8 +68,6 @@ public class CustomButton public static void HudUpdate() { buttons.RemoveAll(item => item.killButtonManager == null); - - if (MeetingHud.Instance || ExileController.Instance) return; for (int i = 0; i < buttons.Count; i++) { @@ -127,7 +125,7 @@ public class CustomButton private void Update() { - if (PlayerControl.LocalPlayer.Data == null || !HasButton()) { + if (PlayerControl.LocalPlayer.IDOFAMCIJKE == null || MeetingHud.Instance || ExileController.Instance || !HasButton()) { setActive(false); return; } @@ -141,10 +139,10 @@ public class CustomButton if (hudManager.KillButton != null) hudManager.KillButton.transform.localPosition = hudManager.UseButton.transform.localPosition - new Vector3(1.3f, 0, 0); // Align the kill button (because it's on another position depending on the screen resolution) } if (CouldUse()) { - killButtonManager.renderer.color = Palette.EnabledColor; + killButtonManager.renderer.color = Palette.MKAFGNEBHKC; killButtonManager.renderer.material.SetFloat("_Desat", 0f); } else { - killButtonManager.renderer.color = Palette.DisabledColor; + killButtonManager.renderer.color = Palette.POCKGPCFGOE; killButtonManager.renderer.material.SetFloat("_Desat", 1f); } @@ -157,7 +155,7 @@ public class CustomButton if (Timer <= 0 && HasEffect && isEffectActive) { isEffectActive = false; - killButtonManager.TimerText.Color = Palette.EnabledColor; + killButtonManager.TimerText.Color = Palette.MKAFGNEBHKC; OnEffectEnds(); } diff --git a/Source Code/CustomOptions.cs b/Source Code/CustomOptions.cs new file mode 100644 index 0000000..b8a26f8 --- /dev/null +++ b/Source Code/CustomOptions.cs @@ -0,0 +1,379 @@ +using System.Collections.Generic; +using UnityEngine; +using BepInEx.Configuration; +using System; +using System.Linq; +using HarmonyLib; +using Hazel; +using System.Reflection; +using System.Text; +using static TheOtherRoles.TheOtherRoles; + +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[] crewmateRoleCaps = new string[]{"0", "0-1", "1", "1-2", "2", "2-3", "3", "3-4", "4", "4-5", "5", "5-6", "6", "6-7", "7", "7-8", "8", "8-9", "9", "9-10", "10"}; + public static string[] impostorRoleCaps = new string[]{"0", "0-1", "1", "1-2", "2", "2-3", "3"}; + public static string[] presets = new string[]{"Preset 1", "Preset 2", "Preset 3", "Preset 4", "Preset 5"}; + + + public static CustomOption presetSelection, crewmateRolesCount, impostorRolesCount; + public static CustomOption mafiaSpawnRate, morphlingSpawnRate, camouflagerSpawnRate, vampireSpawnRate, eraserSpawnRate; + public static CustomOption childSpawnRate, loversSpawnRate, jesterSpawnRate; + public static CustomOption shifterSpawnRate, mayorSpawnRate, engineerSpawnRate, sheriffSpawnRate, lighterSpawnRate, detectiveSpawnRate, timeMasterSpawnRate, medicSpawnRate, swapperSpawnRate, seerSpawnRate, hackerSpawnRate, trackerSpawnRate, snitchSpawnRate, jackalSpawnRate; + public static CustomOption maxNumberOfMeetings; + public static CustomOption janitorCooldown, morphlingCooldown, camouflagerCooldown, vampireKillDelay, vampireCooldown, vampireCanKillNearGarlics, eraserCooldown; + public static CustomOption childGrowingUpDuration, loversImpLoverRate, loversBothDie; + public static CustomOption sheriffCooldown, jesterCanDieToSheriff, lighterModeLightsOnVision, lighterModeLightsOffVision, lighterCooldown, lighterDuration, detectiveAnonymousFootprints, detectiveFootprintIntervall, detectiveFootprintDuration, detectiveReportNameDuration, detectiveReportColorDuration, timeMasterCooldown, timeMasterRewindTime, medicShowShielded, medicShowAttemptToShielded, seerMode, seerSoulDuration, hackerCooldown, hackerHackeringDuration, hackerOnlyColorType, trackerUpdateIntervall, snitchLeftTasksForImpostors, jackalKillCooldown, jackalCreateSidekickCooldown, jackalCanUseVents, jackalCanCreateSidekick, sidekickPromotesToJackal, sidekickCanKill, sidekickCanUseVents, jackalPromotedFromSidekickCanCreateSidekick, jackalCanCreateSidekickFromImpostor; + + public static string cs(Color c, string s) { + return string.Format("[{0:X2}{1:X2}{2:X2}{3:X2}]{4}[]", ToByte(c.r), ToByte(c.g), ToByte(c.b), ToByte(c.a), s); + } + + private static byte ToByte(float f) { + f = Mathf.Clamp01(f); + return (byte)(f * 255); + } + + public static void Load() { + presetSelection = CustomOption.Create(0, "[CCCC00FF]Preset[]", presets); + crewmateRolesCount = CustomOption.Create(1, "[CCCC00FF]Number Of Crewmate/Neutral Roles[]", crewmateRoleCaps); + impostorRolesCount = CustomOption.Create(2, "[CCCC00FF]Number Of Impostor Roles[]", impostorRoleCaps); + + mafiaSpawnRate = CustomOption.Create(10, cs(Janitor.color, "Mafia"), rates); + morphlingSpawnRate = CustomOption.Create(20, cs(Morphling.color, "Morphling"), rates); + camouflagerSpawnRate = CustomOption.Create(30, cs(Camouflager.color, "Camouflager"), rates); + vampireSpawnRate = CustomOption.Create(40, cs(Vampire.color, "Vampire"), rates); + eraserSpawnRate = CustomOption.Create(230, cs(Eraser.color, "Eraser"), rates); + + childSpawnRate = CustomOption.Create(180, cs(Child.color, "Child"), rates); + loversSpawnRate = CustomOption.Create(50, cs(Lovers.color, "Lovers"), rates); + jesterSpawnRate = CustomOption.Create(60, cs(Jester.color, "Jester"), rates); + + shifterSpawnRate = CustomOption.Create(70, cs(Shifter.color, "Shifter"), rates); + mayorSpawnRate = CustomOption.Create(80, cs(Mayor.color, "Mayor"), rates); + engineerSpawnRate = CustomOption.Create(90, cs(Engineer.color, "Engineer"), rates); + sheriffSpawnRate = CustomOption.Create(100, cs(Sheriff.color, "Sheriff"), rates); + lighterSpawnRate = CustomOption.Create(110, cs(Lighter.color, "Lighter"), rates); + detectiveSpawnRate = CustomOption.Create(120, cs(Detective.color, "Detective"), rates); + timeMasterSpawnRate = CustomOption.Create(130, cs(TimeMaster.color, "Time Master"), rates); + medicSpawnRate = CustomOption.Create(140, cs(Medic.color, "Medic"), rates); + swapperSpawnRate = CustomOption.Create(150, cs(Swapper.color, "Swapper"), rates); + seerSpawnRate = CustomOption.Create(160, cs(Seer.color, "Seer"), rates); + hackerSpawnRate = CustomOption.Create(170, cs(Hacker.color, "Hacker"), rates); + trackerSpawnRate = CustomOption.Create(200, cs(Tracker.color, "Tracker"), rates); + snitchSpawnRate = CustomOption.Create(210, cs(Snitch.color, "Snitch"), rates); + jackalSpawnRate = CustomOption.Create(220, cs(Jackal.color, "Jackal"), rates); + + // Map settings + maxNumberOfMeetings = CustomOption.Create(3, "Number Of Meetings (excluding Mayor meeting)", 10, 0, 15, 1); + + // Role settings + janitorCooldown = CustomOption.Create(11, "Janitor Cooldown", 30f, 10f, 60f, 2.5f); + morphlingCooldown = CustomOption.Create(21, "Morphling Cooldown", 30f, 10f, 60f, 2.5f); + camouflagerCooldown = CustomOption.Create(31, "Camouflager Cooldown", 30f, 10f, 60f, 2.5f); + vampireKillDelay = CustomOption.Create(41, "Vampire Kill Delay", 10f, 1f, 20f, 1f); + vampireCooldown = CustomOption.Create(42, "Vampire Cooldown", 30f, 10f, 60f, 2.5f); + vampireCanKillNearGarlics = CustomOption.Create(43, "Vampire Can Kill Near Garlics", true); + eraserCooldown = CustomOption.Create(231, "Eraser Cooldown", 30f, 10f, 120f, 5f); + + childGrowingUpDuration = CustomOption.Create(181, "Child Growing Up Duration", 400f, 100f, 1500f, 100f); + loversImpLoverRate = CustomOption.Create(51, "Chance That One Lover Is Impostor", 30f, 0f, 100f, 10f); + loversBothDie = CustomOption.Create(52, "Both Lovers Die", true); + + sheriffCooldown = CustomOption.Create(101, "Sheriff Cooldown", 30f, 10f, 60f, 2.5f); + jesterCanDieToSheriff = CustomOption.Create(102, "Sheriff Can Kill The Jester", false); + lighterModeLightsOnVision = CustomOption.Create(111, "Lighter Mode Vision On Lights On", 2f, 0.25f, 5f, 0.25f); + lighterModeLightsOffVision = CustomOption.Create(112, "Lighter Mode Vision On Lights Off", 0.75f, 0.25f, 5f, 0.25f); + lighterCooldown = CustomOption.Create(113, "Lighter Cooldown", 30f, 5f, 120f, 5f); + lighterDuration = CustomOption.Create(114, "Lighter Duration", 5f, 2.5f, 60f, 2.5f); + detectiveAnonymousFootprints = CustomOption.Create(121, "Anonymous Footprints", false); + detectiveFootprintIntervall = CustomOption.Create(122, "Footprint Intervall", 0.5f, 0.25f, 10f, 0.25f); + detectiveFootprintDuration = CustomOption.Create(123, "Footprint Duration", 5f, 0.25f, 10f, 0.25f); + detectiveReportNameDuration = CustomOption.Create(124, "Time Where Detective Reports Will Have Name", 0, 0, 60, 2.5f); + detectiveReportColorDuration = CustomOption.Create(125, "Time Where Detective Reports Will Have Color Type", 20, 0, 120, 2.5f); + timeMasterCooldown = CustomOption.Create(131, "Time Master Cooldown", 30f, 10f, 60f, 2.5f); + timeMasterRewindTime = CustomOption.Create(132, "Rewind Time", 3f, 1f, 10f, 1f); + medicShowShielded = CustomOption.Create(143, "Show Shielded Player", new string[] {"Everyone", "Shielded + Medic", "Medic"}); + medicShowAttemptToShielded = CustomOption.Create(144, "Shielded Player Sees Murder Attempt", false); + seerMode = CustomOption.Create(161, "Seer Mode", new string[]{ "Show Death Flash + Souls", "Show Death Flash", "Show Souls"}); + seerSoulDuration = CustomOption.Create(162, "Seer Soul Duration", 15f, 0f, 60f, 5f); + hackerCooldown = CustomOption.Create(171, "Hacker Cooldown", 30f, 0f, 60f, 5f); + hackerHackeringDuration = CustomOption.Create(172, "Hacker Duration", 10f, 2.5f, 60f, 2.5f); + hackerOnlyColorType = CustomOption.Create(173, "Hacker Only Sees Color Type", false); + trackerUpdateIntervall = CustomOption.Create(201, "Tracker Update Intervall", 5f, 2.5f, 30f, 2.5f); + snitchLeftTasksForImpostors = CustomOption.Create(211, "Task Count Where Impostors See Snitch", 1f, 0f, 5f, 1f); + jackalKillCooldown = CustomOption.Create(221, "Jackal/Sidekick Kill Cooldown", 30f, 10f, 60f, 2.5f); + jackalCreateSidekickCooldown = CustomOption.Create(222, "Jackal Create Sidekick Cooldown", 30f, 10f, 60f, 2.5f); + jackalCanUseVents = CustomOption.Create(223, "Jackal can use vents", true); + jackalCanCreateSidekick = CustomOption.Create(224, "Jackal can create a sidekick", false); + sidekickPromotesToJackal = CustomOption.Create(225, "Sidekick gets promoted to Jackal on Jackal death", false); + sidekickCanKill = CustomOption.Create(226, "Sidekick can kill", false); + sidekickCanUseVents = CustomOption.Create(227, "Sidekick can use vents", true); + jackalPromotedFromSidekickCanCreateSidekick = CustomOption.Create(228, "Jackals promoted from Sidekick can create a Sidekick", true); + jackalCanCreateSidekickFromImpostor = CustomOption.Create(229, "Jackals can make an Impostor to his Sidekick", true); + } + } + + public class CustomOption { + public static List options = new List(); + public static int preset = 0; + + public int id; + public string name; + public System.Object[] selections; + + public int defaultSelection; + public ConfigEntry entry; + public int selection; + public OptionBehaviour optionBehaviour; + + // Option creation + + public CustomOption(int id, string name, System.Object[] selections, System.Object defaultValue) { + this.id = id; + this.name = name; + this.selections = selections; + int index = Array.IndexOf(selections, defaultValue); + this.defaultSelection = index >= 0 ? index : 0; + selection = 0; + if (id != 0) { + entry = TheOtherRolesPlugin.Instance.Config.Bind($"Preset{preset}", id.ToString(), defaultSelection); + selection = Mathf.Clamp(entry.Value, 0, selections.Length - 1); + } + options.Add(this); + } + + public static CustomOption Create(int id, string name, string[] selections, string defaultValue = "") { + return new CustomOption(id, name, selections, defaultValue); + } + + public static CustomOption Create(int id, string name, float defaultValue, float min, float max, float step) { + List selections = new List(); + for (float s = min; s <= max; s += step) + selections.Add(s); + return new CustomOption(id, name, selections.Cast().ToArray(), defaultValue); + } + + public static CustomOption Create(int id, string name, bool defaultValue) { + return new CustomOption(id, name, new string[]{"Off", "On"}, default ? "On" : "Off"); + } + + // Static behaviour + + public static void switchPreset(int newPreset) { + CustomOption.preset = newPreset; + foreach (CustomOption option in CustomOption.options) { + if (option.id == 0) continue; + + option.entry = TheOtherRolesPlugin.Instance.Config.Bind($"Preset{preset}", option.id.ToString(), option.defaultSelection); + option.selection = Mathf.Clamp(option.entry.Value, 0, option.selections.Length - 1); + if (option.optionBehaviour != null && option.optionBehaviour is StringOption stringOption) { + stringOption.IOFLMCGMJBA = stringOption.Value = option.selection; + stringOption.ValueText.Text = option.selections[option.selection].ToString(); + } + } + } + + public static void ShareOptionSelections() { + if (PlayerControl.AllPlayerControls.Count <= 1 || AmongUsClient.Instance?.CBKCIKKEJHI == false && PlayerControl.LocalPlayer == null) return; + foreach (CustomOption option in CustomOption.options) { + MessageWriter messageWriter = AmongUsClient.Instance.StartRpc(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.ShareOptionSelection, Hazel.SendOption.Reliable); + messageWriter.WritePacked((uint)option.id); + messageWriter.WritePacked((uint)Convert.ToUInt32(option.selection)); + messageWriter.EndMessage(); + } + } + + // Getter + + public int getSelection() { + return selection; + } + + public bool getBool() { + return selection > 0; + } + + public float getFloat() { + return (float)selections[selection]; + } + + // Option changes + + public void updateSelection(int newSelection) { + selection = Mathf.Clamp((newSelection + selections.Length) % selections.Length, 0, selections.Length - 1); + if (optionBehaviour != null && optionBehaviour is StringOption stringOption) { + stringOption.IOFLMCGMJBA = stringOption.Value = selection; + stringOption.ValueText.Text = selections[selection].ToString(); + + if (AmongUsClient.Instance?.CBKCIKKEJHI == true && PlayerControl.LocalPlayer) { + if (id == 0) switchPreset(selection); // Switch presets + else if (entry != null) entry.Value = selection; // Save selection to config + + ShareOptionSelections();// Share all selections + } + } + } + } + + [HarmonyPatch(typeof(GameOptionsMenu), nameof(GameOptionsMenu.Start))] + class GameOptionsMenuStartPatch { + public static void Postfix(GameOptionsMenu __instance) { + var template = UnityEngine.Object.FindObjectsOfType().FirstOrDefault(); + if (template == null) return; + + List allOptions = __instance.IGFJIPMAJHF.ToList(); + for (int i = 0; i < CustomOption.options.Count; i++) { + CustomOption option = CustomOption.options[i]; + if (option.optionBehaviour == null) { + StringOption stringOption = UnityEngine.Object.Instantiate(template, template.transform.parent); + allOptions.Add(stringOption); + stringOption.transform.localPosition = new Vector3(template.transform.localPosition.x, -7.85f - (i + 1) * 0.5F, template.transform.localPosition.z); + + stringOption.OnValueChanged = new Action((o) => {}); + stringOption.TitleText.Text = option.name; + stringOption.Value = stringOption.IOFLMCGMJBA = option.selection; + stringOption.ValueText.Text = option.selections[option.selection].ToString(); + + option.optionBehaviour = stringOption; + } + option.optionBehaviour.gameObject.SetActive(true); + } + __instance.IGFJIPMAJHF = allOptions.ToArray(); + } + } + + [HarmonyPatch(typeof(StringOption), nameof(StringOption.OnEnable))] + public class StringOptionEnablePatch { + public static bool Prefix(StringOption __instance) { + CustomOption option = CustomOption.options.FirstOrDefault(option => option.optionBehaviour == __instance); + if (option == null) return true; + + __instance.OnValueChanged = new Action((o) => {}); + __instance.TitleText.Text = option.name; + __instance.Value = __instance.IOFLMCGMJBA = option.selection; + __instance.ValueText.Text = option.selections[option.selection].ToString(); + + return false; + } + } + + [HarmonyPatch(typeof(StringOption), nameof(StringOption.Increase))] + public class StringOptionIncreasePatch + { + public static bool Prefix(StringOption __instance) + { + CustomOption option = CustomOption.options.FirstOrDefault(option => option.optionBehaviour == __instance); + if (option == null) return true; + option.updateSelection(option.selection + 1); + return false; + } + } + + [HarmonyPatch(typeof(StringOption), nameof(StringOption.Decrease))] + public class StringOptionDecreasePatch + { + public static bool Prefix(StringOption __instance) + { + CustomOption option = CustomOption.options.FirstOrDefault(option => option.optionBehaviour == __instance); + if (option == null) return true; + option.updateSelection(option.selection - 1); + return false; + } + } + + [HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.RpcSyncSettings))] + public class RpcSyncSettingsPatch + { + public static void Postfix() + { + CustomOption.ShareOptionSelections(); + } + } + + + [HarmonyPatch(typeof(GameOptionsMenu), nameof(GameOptionsMenu.Update))] + class GameOptionsMenuUpdatePatch + { + public static void Postfix(GameOptionsMenu __instance) { + __instance.GetComponentInParent().YBounds.max = -0.5F + __instance.IGFJIPMAJHF.Length * 0.5F; + } + } + + [HarmonyPatch(typeof(GameSettingMenu), "OnEnable")] + class GameSettingMenuPatch { + public static void Prefix(GameSettingMenu __instance) { + __instance.HideForOnline = new Transform[]{}; + } + } + + [HarmonyPatch] + class GameOptionsDataPatch + { + private static IEnumerable TargetMethods() { + return typeof(IGDMNKLDEPI).GetMethods().Where(x => x.ReturnType == typeof(string) && x.GetParameters().Length == 1 && x.GetParameters()[0].ParameterType == typeof(int)); + } + + private static void Postfix(ref string __result) + { + StringBuilder sb = new StringBuilder(__result); + foreach (CustomOption option in CustomOption.options) { + sb.AppendLine($"{option.name}: {option.selections[option.selection].ToString()}"); + } + var hudString = sb.ToString(); + + int defaultSettingsLines = 19; + int roleSettingsLines = 19 + 25; + int detailedSettingsLines = 19 + 25 + 25; + int end1 = hudString.TakeWhile(c => (defaultSettingsLines -= (c == '\n' ? 1 : 0)) > 0).Count(); + int end2 = hudString.TakeWhile(c => (roleSettingsLines -= (c == '\n' ? 1 : 0)) > 0).Count(); + int end3 = hudString.TakeWhile(c => (detailedSettingsLines -= (c == '\n' ? 1 : 0)) > 0).Count(); + int counter = TheOtherRolesPlugin.optionsPage; + if (counter == 0) { + hudString = hudString.Substring(0, end1) + "\n"; + } else if (counter == 1) { + hudString = hudString.Substring(end1 + 1, end2 - end1); + // Temporary fix, should add a new CustomOption for spaces + int gap = 1; + int index = hudString.TakeWhile(c => (gap -= (c == '\n' ? 1 : 0)) > 0).Count(); + hudString = hudString.Insert(index, "\n"); + gap = 4; + index = hudString.TakeWhile(c => (gap -= (c == '\n' ? 1 : 0)) > 0).Count(); + hudString = hudString.Insert(index, "\n"); + gap = 10; + index = hudString.TakeWhile(c => (gap -= (c == '\n' ? 1 : 0)) > 0).Count(); + hudString = hudString.Insert(index + 1, "\n"); + gap = 14; + index = hudString.TakeWhile(c => (gap -= (c == '\n' ? 1 : 0)) > 0).Count(); + hudString = hudString.Insert(index + 1, "\n"); + } else if (counter == 2) { + hudString = hudString.Substring(end2 + 1, end3 - end2); + } else if (counter == 3) { + hudString = hudString.Substring(end3 + 1); + } + + hudString += $"\n Press tab for more... ({counter+1}/4)"; + __result = hudString; + } + } + + [HarmonyPatch(typeof(KeyboardJoystick), nameof(KeyboardJoystick.Update))] + public static class GameOptionsNextPagePatch + { + public static void Postfix(KeyboardJoystick __instance) + { + if(Input.GetKeyDown(KeyCode.Tab)) { + TheOtherRolesPlugin.optionsPage = (TheOtherRolesPlugin.optionsPage + 1) % 4; + } + } + } + + + [HarmonyPatch(typeof(HudManager), nameof(HudManager.Update))] + public class GameSettingsScalePatch { + public static void Prefix(HudManager __instance) { + __instance.GameSettings.scale = 0.5f; + } + } +} \ No newline at end of file diff --git a/Source Code/EndGamePatch.cs b/Source Code/EndGamePatch.cs index 36a12c4..897e4aa 100644 --- a/Source Code/EndGamePatch.cs +++ b/Source Code/EndGamePatch.cs @@ -11,10 +11,20 @@ using UnhollowerBaseLib; using System; using System.Text; +using GameOverReason = JBJHCLOILBF; +using TempData = DIJKKMDMDCM; +using WinningPlayerData = KBEBEPNGKOD; +using DeathReason = KAPJFCMEBJE; +using SystemTypes = LGBKLKNAINN; +using ISystemType = CBFMKGACLNE; +using LifeSuppSystemType = MHEBFNFMKPH; +using ICriticalSabotage = IEGIFFLBFJG; + namespace TheOtherRoles { enum CustomGameOverReason { LoversWin = 10, - TeamJackalWin = 11 + TeamJackalWin = 11, + ChildLose = 12 } enum WinCondition { @@ -24,7 +34,8 @@ namespace TheOtherRoles { JesterWin, BountyHunterWin, JesterAndBountyHunterWin, - JackalWin + JackalWin, + ChildLose } static class AdditionalTempData { @@ -40,66 +51,69 @@ namespace TheOtherRoles { } } - [HarmonyPatch(typeof(AmongUsClient), nameof(AmongUsClient.OnGameEnd))] + [HarmonyPatch(typeof(AmongUsClient), nameof(AmongUsClient.MDDLANONDOD))] public class OnGameEndPatch { private static GameOverReason gameOverReason; - public static void Prefix(AmongUsClient __instance, ref GameOverReason OFLKLGMHBEL, bool JFFPAKGPNJA) { - gameOverReason = OFLKLGMHBEL; - if ((int)OFLKLGMHBEL >= 10) OFLKLGMHBEL = GameOverReason.ImpostorByKill; + public static void Prefix(AmongUsClient __instance, ref GameOverReason FCBGPMEMOJB, bool GKFHPFPIHGA) { + gameOverReason = FCBGPMEMOJB; + if ((int)FCBGPMEMOJB >= 10) FCBGPMEMOJB = GameOverReason.ImpostorByKill; } - public static void Postfix(AmongUsClient __instance, GameOverReason OFLKLGMHBEL, bool JFFPAKGPNJA) { + public static void Postfix(AmongUsClient __instance, GameOverReason FCBGPMEMOJB, bool GKFHPFPIHGA) { AdditionalTempData.clear(); - // Remove shifter from winners - if (Shifter.shifter != null) { - WinningPlayerData shifterWinner = null; - foreach (WinningPlayerData winner in TempData.winners) - if (winner.Name == Shifter.shifter.Data.PlayerName) shifterWinner = winner; - - if (shifterWinner != null) TempData.winners.Remove(shifterWinner); - } // Remove Jester from winners (on Jester win he will be added again, see below) if (Jester.jester != null) { WinningPlayerData jesterWinner = null; - foreach (WinningPlayerData winner in TempData.winners) - if (winner.Name == Jester.jester.Data.PlayerName) jesterWinner = winner; + foreach (WinningPlayerData winner in TempData.BDGOKPKHCNB) + if (winner.GEDNCGBDPKC == Jester.jester.IDOFAMCIJKE.HGGCLJHCDBM) jesterWinner = winner; - if (jesterWinner != null) TempData.winners.Remove(jesterWinner); + if (jesterWinner != null) TempData.BDGOKPKHCNB.Remove(jesterWinner); } // Remove Jackal and Sidekick from winners (on Jackal win he will be added again, see below) if (Jackal.jackal != null || Sidekick.sidekick != null) { List winnersToRemove = new List(); - foreach (WinningPlayerData winner in TempData.winners) { - if (winner.Name == Jackal.jackal?.Data?.PlayerName) winnersToRemove.Add(winner); - if (winner.Name == Sidekick.sidekick?.Data?.PlayerName) winnersToRemove.Add(winner); + foreach (WinningPlayerData winner in TempData.BDGOKPKHCNB) { + if (winner.GEDNCGBDPKC == Jackal.jackal?.IDOFAMCIJKE?.HGGCLJHCDBM) winnersToRemove.Add(winner); + if (winner.GEDNCGBDPKC == Sidekick.sidekick?.IDOFAMCIJKE?.HGGCLJHCDBM) winnersToRemove.Add(winner); foreach(var player in Jackal.formerJackals) { - if (winner.Name == player.Data.PlayerName) { + if (winner.GEDNCGBDPKC == player.IDOFAMCIJKE.HGGCLJHCDBM) { winnersToRemove.Add(winner); } } } foreach (var winner in winnersToRemove) { - TempData.winners.Remove(winner); + TempData.BDGOKPKHCNB.Remove(winner); } } + bool childLose = Child.child != null && gameOverReason == (GameOverReason)CustomGameOverReason.ChildLose; + bool jesterWin = Jester.jester != null && Jester.jester.IDOFAMCIJKE.CIDDOFDJHJH; + bool bountyHunterWin = BountyHunter.bountyHunter != null && BountyHunter.bountyHunter.IDOFAMCIJKE.CIDDOFDJHJH; + + // Child lose condition (should be implemented using a proper GameOverReason in the future) + if (childLose) { + TempData.BDGOKPKHCNB = new Il2CppSystem.Collections.Generic.List(); + WinningPlayerData wpd = new WinningPlayerData(Child.child.IDOFAMCIJKE); + wpd.KCEFGIGGLHM = false; // If "no one is the Child", it will display the Child, but also show defeat to everyone + TempData.BDGOKPKHCNB.Add(wpd); + AdditionalTempData.winCondition = WinCondition.ChildLose; + } + // Jester and Bounty Hunter win condition (should be implemented using a proper GameOverReason in the future) - bool jesterWin = Jester.jester != null && Jester.jester.Data.IsImpostor; - bool bountyHunterWin = BountyHunter.bountyHunter != null && BountyHunter.bountyHunter.Data.IsImpostor; - if (jesterWin || bountyHunterWin) { - TempData.winners = new Il2CppSystem.Collections.Generic.List(); + else if (jesterWin || bountyHunterWin) { + TempData.BDGOKPKHCNB = new Il2CppSystem.Collections.Generic.List(); if (jesterWin) { - WinningPlayerData wpd = new WinningPlayerData(Jester.jester.Data); - wpd.IsImpostor = false; - TempData.winners.Add(wpd); + WinningPlayerData wpd = new WinningPlayerData(Jester.jester.IDOFAMCIJKE); + wpd.CIDDOFDJHJH = false; + TempData.BDGOKPKHCNB.Add(wpd); AdditionalTempData.winCondition = WinCondition.JesterWin; } if (bountyHunterWin) { - WinningPlayerData wpd = new WinningPlayerData(BountyHunter.bountyHunter.Data); - wpd.IsImpostor = false; - TempData.winners.Add(wpd); + WinningPlayerData wpd = new WinningPlayerData(BountyHunter.bountyHunter.IDOFAMCIJKE); + wpd.CIDDOFDJHJH = false; + TempData.BDGOKPKHCNB.Add(wpd); if (AdditionalTempData.winCondition == WinCondition.JesterWin) AdditionalTempData.winCondition = WinCondition.JesterAndBountyHunterWin; else @@ -113,52 +127,51 @@ namespace TheOtherRoles { // Double win for lovers, crewmates also win if (!Lovers.existingWithImpLover()) { AdditionalTempData.winCondition = WinCondition.LoversTeamWin; - TempData.winners = new Il2CppSystem.Collections.Generic.List(); + TempData.BDGOKPKHCNB = new Il2CppSystem.Collections.Generic.List(); foreach (PlayerControl p in PlayerControl.AllPlayerControls) { if (p == null) continue; if (p == Lovers.lover1 || p == Lovers.lover2) - TempData.winners.Add(new WinningPlayerData(p.Data)); - else if (p != Shifter.shifter && p != Jester.jester && p != Jackal.jackal && p != Sidekick.sidekick && !p.Data.IsImpostor) - TempData.winners.Add(new WinningPlayerData(p.Data)); + TempData.BDGOKPKHCNB.Add(new WinningPlayerData(p.IDOFAMCIJKE)); + else if (p != Jester.jester && p != Jackal.jackal && p != Sidekick.sidekick && !p.IDOFAMCIJKE.CIDDOFDJHJH) + TempData.BDGOKPKHCNB.Add(new WinningPlayerData(p.IDOFAMCIJKE)); } } // Lovers solo win else { AdditionalTempData.winCondition = WinCondition.LoversSoloWin; - TempData.winners = new Il2CppSystem.Collections.Generic.List(); - TempData.winners.Add(new WinningPlayerData(Lovers.lover1.Data)); - TempData.winners.Add(new WinningPlayerData(Lovers.lover2.Data)); + TempData.BDGOKPKHCNB = new Il2CppSystem.Collections.Generic.List(); + TempData.BDGOKPKHCNB.Add(new WinningPlayerData(Lovers.lover1.IDOFAMCIJKE)); + TempData.BDGOKPKHCNB.Add(new WinningPlayerData(Lovers.lover2.IDOFAMCIJKE)); } } // Jackal win condition (should be implemented using a proper GameOverReason in the future) - else if (gameOverReason == (GameOverReason)CustomGameOverReason.TeamJackalWin && (Jackal.jackal != null && !Jackal.jackal.Data.IsDead || Sidekick.sidekick != null && !Sidekick.sidekick.Data.IsDead)) { + else if (gameOverReason == (GameOverReason)CustomGameOverReason.TeamJackalWin && (Jackal.jackal != null && !Jackal.jackal.IDOFAMCIJKE.FGNJJFABIHJ || Sidekick.sidekick != null && !Sidekick.sidekick.IDOFAMCIJKE.FGNJJFABIHJ)) { // Jackal wins if nobody except jackal is alive AdditionalTempData.winCondition = WinCondition.JackalWin; - TempData.winners = new Il2CppSystem.Collections.Generic.List(); - WinningPlayerData wpd = new WinningPlayerData(Jackal.jackal.Data); - wpd.IsImpostor = false; - TempData.winners.Add(wpd); + TempData.BDGOKPKHCNB = new Il2CppSystem.Collections.Generic.List(); + WinningPlayerData wpd = new WinningPlayerData(Jackal.jackal.IDOFAMCIJKE); + wpd.CIDDOFDJHJH = false; + TempData.BDGOKPKHCNB.Add(wpd); // If there is a sidekick. The sidekick also wins if (Sidekick.sidekick != null) { - WinningPlayerData wpdSidekick = new WinningPlayerData(Sidekick.sidekick.Data); - wpdSidekick.IsImpostor = false; - TempData.winners.Add(wpdSidekick); + WinningPlayerData wpdSidekick = new WinningPlayerData(Sidekick.sidekick.IDOFAMCIJKE); + wpdSidekick.CIDDOFDJHJH = false; + TempData.BDGOKPKHCNB.Add(wpdSidekick); } foreach(var player in Jackal.formerJackals) { - WinningPlayerData wpdFormerJackal = new WinningPlayerData(player.Data); - wpdFormerJackal.IsImpostor = false; - TempData.winners.Add(wpdFormerJackal); + WinningPlayerData wpdFormerJackal = new WinningPlayerData(player.IDOFAMCIJKE); + wpdFormerJackal.CIDDOFDJHJH = false; + TempData.BDGOKPKHCNB.Add(wpdFormerJackal); } } - // Reset Role Settings - clearAndReloadRoles(); - clearGameHistory(); + // Reset Settings + RPCProcedure.resetVariables(); } } - [HarmonyPatch(typeof(EndGameManager), nameof(EndGameManager.SetEverythingUp))] + [HarmonyPatch(typeof(EndGameManager), nameof(EndGameManager.BIGANIAENKO))] public class EndGameManagerSetUpPatch { public static void Postfix(EndGameManager __instance) { GameObject bonusText = UnityEngine.Object.Instantiate(__instance.WinText.gameObject); @@ -196,17 +209,22 @@ namespace TheOtherRoles { textRenderer.Text = "Team Jackal Wins"; textRenderer.Color = Jackal.color; } + else if (AdditionalTempData.winCondition == WinCondition.ChildLose) { + textRenderer.Text = "Child died"; + textRenderer.Color = Child.color; + } AdditionalTempData.clear(); } } - [HarmonyPatch(typeof(ShipStatus), nameof(ShipStatus.CheckEndCriteria))] + [HarmonyPatch(typeof(ShipStatus), nameof(ShipStatus.NBEBPPBCGLJ))] class CheckEndCriteriaPatch{ public static bool Prefix(ShipStatus __instance) { if (!GameData.Instance) return false; var statistics = new PlayerStatistics(__instance); + if (CheckAndEndGameForChildLose(__instance)) return false; if(CheckAndEndGameForSabotageWin(__instance)) return false; if(CheckAndEndGameForTaskWin(__instance)) return false; if(CheckAndEndGameForLoverWin(__instance, statistics)) return false; @@ -216,13 +234,29 @@ namespace TheOtherRoles { return false; } + private static bool CheckAndEndGameForChildLose(ShipStatus __instance) { + if (Child.triggerChildLose) { + if (!DestroyableSingleton.JECNDKBIOFO) + { + __instance.enabled = false; + ShipStatus.PBKIGLMJEDH((GameOverReason)CustomGameOverReason.ChildLose, false); + } + DestroyableSingleton.CMJOLNCMAPD.ShowPopUp(DestroyableSingleton.CMJOLNCMAPD.GetString(StringNames.GameOverImpostorDead, new Il2CppReferenceArray(0))); + ReviveEveryone(); + return true; + } + return false; + } + + private static bool CheckAndEndGameForSabotageWin(ShipStatus __instance) { + if (__instance.Systems == null) return false; ISystemType systemType = __instance.Systems.ContainsKey(SystemTypes.LifeSupp) ? __instance.Systems[SystemTypes.LifeSupp] : null; if (systemType != null) { LifeSuppSystemType lifeSuppSystemType = systemType.TryCast(); - if (lifeSuppSystemType.Countdown < 0f) { + if (lifeSuppSystemType != null && lifeSuppSystemType.DFAOAPHABEF < 0f) { EndGameForSabotage(__instance); - lifeSuppSystemType.Countdown = 10000f; + lifeSuppSystemType.DFAOAPHABEF = 10000f; return true; } } @@ -231,10 +265,10 @@ namespace TheOtherRoles { systemType2 = __instance.Systems.ContainsKey(SystemTypes.Laboratory) ? __instance.Systems[SystemTypes.Laboratory] : null; } if (systemType2 != null) { - ReactorSystemType reactorSystemType = systemType2.TryCast(); - if (reactorSystemType.Countdown < 0f) { + ICriticalSabotage criticalSystem = systemType2.TryCast(); + if (criticalSystem != null && criticalSystem.DFAOAPHABEF < 0f) { EndGameForSabotage(__instance); - reactorSystemType.Countdown = 10000f; + criticalSystem.ClearSabotage(); return true; } } @@ -244,21 +278,21 @@ namespace TheOtherRoles { private static bool CheckAndEndGameForTaskWin(ShipStatus __instance) { bool localCompletedAllTasks = true; foreach (PlayerTask t in PlayerControl.LocalPlayer.myTasks) { - localCompletedAllTasks = localCompletedAllTasks && t.IsComplete; + localCompletedAllTasks = localCompletedAllTasks && t.MOHGOCFFHLF; } - if (!DestroyableSingleton.InstanceExists) + if (!DestroyableSingleton.JECNDKBIOFO) { if (GameData.Instance.TotalTasks <= GameData.Instance.CompletedTasks) { __instance.enabled = false; - ShipStatus.RpcEndGame(GameOverReason.HumansByTask, false); + ShipStatus.PBKIGLMJEDH(GameOverReason.HumansByTask, false); return true; } } else if (localCompletedAllTasks) { - DestroyableSingleton.Instance.ShowPopUp(DestroyableSingleton.Instance.GetString(StringNames.GameOverTaskWin, new Il2CppReferenceArray(0))); + DestroyableSingleton.CMJOLNCMAPD.ShowPopUp(DestroyableSingleton.CMJOLNCMAPD.GetString(StringNames.GameOverTaskWin, new Il2CppReferenceArray(0))); __instance.Begin(); } return false; @@ -266,13 +300,13 @@ namespace TheOtherRoles { private static bool CheckAndEndGameForLoverWin(ShipStatus __instance, PlayerStatistics statistics) { if (statistics.TeamLoversAlive == 2 && statistics.TotalAlive <= 3) { - if (!DestroyableSingleton.InstanceExists) + if (!DestroyableSingleton.JECNDKBIOFO) { __instance.enabled = false; - ShipStatus.RpcEndGame((GameOverReason)CustomGameOverReason.LoversWin, false); // should be implemented using a proper GameOverReason in the future + ShipStatus.PBKIGLMJEDH((GameOverReason)CustomGameOverReason.LoversWin, false); return true; } - DestroyableSingleton.Instance.ShowPopUp(DestroyableSingleton.Instance.GetString(StringNames.GameOverImpostorDead, new Il2CppReferenceArray(0))); + DestroyableSingleton.CMJOLNCMAPD.ShowPopUp(DestroyableSingleton.CMJOLNCMAPD.GetString(StringNames.GameOverImpostorDead, new Il2CppReferenceArray(0))); ReviveEveryone(); return true; } @@ -281,13 +315,13 @@ namespace TheOtherRoles { private static bool CheckAndEndGameForJackalWin(ShipStatus __instance, PlayerStatistics statistics) { if (statistics.TeamJackalAlive >= statistics.TotalAlive - statistics.TeamJackalAlive && statistics.TeamImpostorsAlive == 0 && !(statistics.TeamJackalHasAliveLover && statistics.TeamLoversAlive == 2)) { - if (!DestroyableSingleton.InstanceExists) + if (!DestroyableSingleton.JECNDKBIOFO) { __instance.enabled = false; - ShipStatus.RpcEndGame((GameOverReason)CustomGameOverReason.TeamJackalWin, false); + ShipStatus.PBKIGLMJEDH((GameOverReason)CustomGameOverReason.TeamJackalWin, false); return true; } - DestroyableSingleton.Instance.ShowPopUp(DestroyableSingleton.Instance.GetString(StringNames.GameOverImpostorKills, new Il2CppReferenceArray(0))); + DestroyableSingleton.CMJOLNCMAPD.ShowPopUp(DestroyableSingleton.CMJOLNCMAPD.GetString(StringNames.GameOverImpostorKills, new Il2CppReferenceArray(0))); ReviveEveryone(); return true; } @@ -296,10 +330,10 @@ namespace TheOtherRoles { private static bool CheckAndEndGameForImpostorWin(ShipStatus __instance, PlayerStatistics statistics) { if (statistics.TeamImpostorsAlive >= statistics.TotalAlive - statistics.TeamImpostorsAlive && statistics.TeamJackalAlive == 0 && !(statistics.TeamImpostorHasAliveLover && statistics.TeamLoversAlive == 2)) { - if (!DestroyableSingleton.InstanceExists) { + if (!DestroyableSingleton.JECNDKBIOFO) { __instance.enabled = false; GameOverReason endReason; - switch (TempData.LastDeathReason) { + switch (TempData.EBGJMGKCIFN) { case DeathReason.Exile: endReason = GameOverReason.ImpostorByVote; break; @@ -310,10 +344,10 @@ namespace TheOtherRoles { endReason = GameOverReason.ImpostorByVote; break; } - ShipStatus.RpcEndGame(endReason, false); + ShipStatus.PBKIGLMJEDH(endReason, false); return true; } - DestroyableSingleton.Instance.ShowPopUp(DestroyableSingleton.Instance.GetString(StringNames.GameOverImpostorKills, new Il2CppReferenceArray(0))); + DestroyableSingleton.CMJOLNCMAPD.ShowPopUp(DestroyableSingleton.CMJOLNCMAPD.GetString(StringNames.GameOverImpostorKills, new Il2CppReferenceArray(0))); ReviveEveryone(); return true; } @@ -322,12 +356,12 @@ namespace TheOtherRoles { private static bool CheckAndEndGameForCrewmateWin(ShipStatus __instance, PlayerStatistics statistics) { if (statistics.TeamImpostorsAlive == 0 && statistics.TeamJackalAlive == 0) { - if (!DestroyableSingleton.InstanceExists) { + if (!DestroyableSingleton.JECNDKBIOFO) { __instance.enabled = false; - ShipStatus.RpcEndGame(GameOverReason.HumansByVote, false); + ShipStatus.PBKIGLMJEDH(GameOverReason.HumansByVote, false); return true; } - DestroyableSingleton.Instance.ShowPopUp(DestroyableSingleton.Instance.GetString(StringNames.GameOverImpostorDead, new Il2CppReferenceArray(0))); + DestroyableSingleton.CMJOLNCMAPD.ShowPopUp(DestroyableSingleton.CMJOLNCMAPD.GetString(StringNames.GameOverImpostorDead, new Il2CppReferenceArray(0))); ReviveEveryone(); return true; } @@ -335,21 +369,21 @@ namespace TheOtherRoles { } private static void ReviveEveryone() { - for (int i = 0; i < GameData.Instance.PlayerCount; i++) - GameData.Instance.AllPlayers[i].Object.Revive(); + for (int i = 0; i < GameData.Instance.BCFPPIDIMJK; i++) + GameData.Instance.AllPlayers[i].GPBBCHGPABL.Revive(); DeadBody[] array = UnityEngine.Object.FindObjectsOfType(); for (int i = 0; i < array.Length; i++) UnityEngine.Object.Destroy(array[i].gameObject); } private static void EndGameForSabotage(ShipStatus __instance) { - if (!DestroyableSingleton.InstanceExists) + if (!DestroyableSingleton.JECNDKBIOFO) { __instance.enabled = false; - ShipStatus.RpcEndGame(GameOverReason.ImpostorBySabotage, false); + ShipStatus.PBKIGLMJEDH(GameOverReason.ImpostorBySabotage, false); return; } - DestroyableSingleton.Instance.ShowPopUp(DestroyableSingleton.Instance.GetString(StringNames.GameOverSabotage, new Il2CppReferenceArray(0))); + DestroyableSingleton.CMJOLNCMAPD.ShowPopUp(DestroyableSingleton.CMJOLNCMAPD.GetString(StringNames.GameOverSabotage, new Il2CppReferenceArray(0))); ReviveEveryone(); } @@ -364,14 +398,14 @@ namespace TheOtherRoles { public bool TeamJackalHasAliveLover {get;set;} public PlayerStatistics(ShipStatus __instance) { - GetPlayerCounts(); + GetBCFPPIDIMJKs(); } - private bool isLover(GameData.PlayerInfo p) { - return (Lovers.lover1 != null && Lovers.lover1.PlayerId == p.PlayerId) || (Lovers.lover2 != null && Lovers.lover2.PlayerId == p.PlayerId); + private bool isLover(GameData.OFKOJOKOOAK p) { + return (Lovers.lover1 != null && Lovers.lover1.PlayerId == p.GMBAIPNOKLP) || (Lovers.lover2 != null && Lovers.lover2.PlayerId == p.GMBAIPNOKLP); } - private void GetPlayerCounts() { + private void GetBCFPPIDIMJKs() { int numJackalAlive = 0; int numImpostorsAlive = 0; int numLoversAlive = 0; @@ -379,27 +413,27 @@ namespace TheOtherRoles { bool impLover = false; bool jackalLover = false; - for (int i = 0; i < GameData.Instance.PlayerCount; i++) + for (int i = 0; i < GameData.Instance.BCFPPIDIMJK; i++) { - GameData.PlayerInfo playerInfo = GameData.Instance.AllPlayers[i]; - if (!playerInfo.Disconnected) + GameData.OFKOJOKOOAK OFKOJOKOOAK = GameData.Instance.AllPlayers[i]; + if (!OFKOJOKOOAK.GBPMEHJFECK) { - if (!playerInfo.IsDead) + if (!OFKOJOKOOAK.FGNJJFABIHJ) { numTotalAlive++; - bool lover = isLover(playerInfo); + bool lover = isLover(OFKOJOKOOAK); if (lover) numLoversAlive++; - if (playerInfo.IsImpostor) { + if (OFKOJOKOOAK.CIDDOFDJHJH) { numImpostorsAlive++; if (lover) impLover = true; } - if (Jackal.jackal != null && Jackal.jackal.PlayerId == playerInfo.PlayerId) { + if (Jackal.jackal != null && Jackal.jackal.PlayerId == OFKOJOKOOAK.GMBAIPNOKLP) { numJackalAlive++; if (lover) jackalLover = true; } - if (Sidekick.sidekick != null && Sidekick.sidekick.PlayerId == playerInfo.PlayerId) { + if (Sidekick.sidekick != null && Sidekick.sidekick.PlayerId == OFKOJOKOOAK.GMBAIPNOKLP) { numJackalAlive++; if (lover) jackalLover = true; } diff --git a/Source Code/Footprint.cs b/Source Code/Footprint.cs index ac41abc..e5978bd 100644 --- a/Source Code/Footprint.cs +++ b/Source Code/Footprint.cs @@ -4,6 +4,9 @@ using System.Collections; using UnityEngine; using static TheOtherRoles.TheOtherRoles; +using Palette = GLNPIJPGGNJ; +using Effects = HLPCBNMDEHF; + namespace TheOtherRoles{ class Footprint { private static List footprints = new List(); @@ -11,6 +14,8 @@ namespace TheOtherRoles{ private Color color; private GameObject footprint; private SpriteRenderer spriteRenderer; + private PlayerControl owner; + private bool anonymousFootprints; public static Sprite getFootprintSprite() { if (sprite) return sprite; @@ -19,10 +24,12 @@ namespace TheOtherRoles{ } public Footprint(float footprintDuration, bool anonymousFootprints, PlayerControl player) { + this.owner = player; + this.anonymousFootprints = anonymousFootprints; if (anonymousFootprints) - this.color = new Color(0.2f, 0.2f, 0.2f, 1f); + this.color = Palette.CALCLMEEPGL[6]; else - this.color = Palette.PlayerColors[(int) player.Data.ColorId]; + this.color = Palette.CALCLMEEPGL[(int) player.IDOFAMCIJKE.JFHFMIKFHGG]; footprint = new GameObject("Footprint"); Vector3 position = new Vector3(player.transform.position.x, player.transform.position.y, player.transform.position.z + 1f); @@ -40,18 +47,22 @@ namespace TheOtherRoles{ footprint.SetActive(true); footprints.Add(this); - Reactor.Coroutines.Start(CoFadeOutAndDestroy(footprintDuration)); - } + PlayerControl.LocalPlayer.StartCoroutine(Effects.LDACHPMFOIF(footprintDuration, new Action((p) => { + Color c = color; + if (!anonymousFootprints && owner != null) { + if (owner == Morphling.morphling && Morphling.morphTimer > 0 && Morphling.morphTarget?.IDOFAMCIJKE != null) + c = Palette.CHIIBPFJACF[Morphling.morphTarget.IDOFAMCIJKE.JFHFMIKFHGG]; + else if (Camouflager.camouflageTimer > 0) + c = Palette.CALCLMEEPGL[6]; + } - IEnumerator CoFadeOutAndDestroy(float duration) - { - for (float t = 0f; t < duration; t += Time.deltaTime) { - if (spriteRenderer) spriteRenderer.color = new Color(color.r, color.g, color.b, Mathf.Clamp(1f - t/duration, 0f, 1f)); + if (spriteRenderer) spriteRenderer.color = new Color(c.r, c.g, c.b, Mathf.Clamp01(1 - p)); - yield return null; + if (p == 1f && footprint != null) { + UnityEngine.Object.Destroy(footprint); + footprints.Remove(this); } - UnityEngine.Object.Destroy(footprint); - footprints.Remove(this); + }))); } } } \ No newline at end of file diff --git a/Source Code/GameHistory.cs b/Source Code/GameHistory.cs index f4b6633..30c7e9e 100644 --- a/Source Code/GameHistory.cs +++ b/Source Code/GameHistory.cs @@ -4,6 +4,8 @@ using System; using UnityEngine; using static TheOtherRoles.TheOtherRoles; +using DeathReason = KAPJFCMEBJE; + namespace TheOtherRoles{ public class DeadPlayer { diff --git a/Source Code/GameOptionsPatch.cs b/Source Code/GameOptionsPatch.cs deleted file mode 100644 index ef19ab3..0000000 --- a/Source Code/GameOptionsPatch.cs +++ /dev/null @@ -1,85 +0,0 @@ -using HarmonyLib; -using System; -using System.IO; -using System.Net.Http; -using UnityEngine; -using static TheOtherRoles.TheOtherRoles; -using Reactor.Extensions; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Text; -using Essentials.Options; - -namespace TheOtherRoles -{ - [HarmonyPriority(Priority.Low)] - [HarmonyPatch(typeof(GameOptionsMenu), nameof(GameOptionsMenu.Update))] - class GameOptionsMenuUpdatePatch - { - public static void Postfix(GameOptionsMenu __instance) - { - __instance.GetComponentInParent().YBounds.max = -0.5F + __instance.Children.Length * 0.5F; - } - } - - [HarmonyPatch(typeof(KeyboardJoystick), nameof(KeyboardJoystick.Update))] - public static class GameOptionsNextPagePatch - { - private static readonly System.Random random = new System.Random((int)DateTime.Now.Ticks); - private static List bots = new List(); - - public static void Postfix(KeyboardJoystick __instance) - { - if(Input.GetKeyDown(KeyCode.Tab)) { - TheOtherRolesPlugin.optionsPage = (TheOtherRolesPlugin.optionsPage + 1) % 3; - } - } - } - - [HarmonyPatch(typeof(GameOptionsData), "NHJLMAAHKJF")] - class GameOptionsDataPatch - { - - private static void Postfix(ref string __result) - { - StringBuilder stringBuilder = new StringBuilder(__result); - foreach (CustomOption customOption in TheOtherRolesPlugin.options) { - stringBuilder.AppendLine(string.Format("{0}[]: {1}", customOption.Name, customOption)); - } - var hudString = stringBuilder.ToString(); - - int defaultSettingsLines = 19; - int roleSettingsLines = 19 + 23; - int end1 = hudString.TakeWhile(c => (defaultSettingsLines -= (c == '\n' ? 1 : 0)) > 0).Count(); - int end2 = hudString.TakeWhile(c => (roleSettingsLines -= (c == '\n' ? 1 : 0)) > 0).Count(); - int counter = TheOtherRolesPlugin.optionsPage; - if (counter == 0) { - hudString = hudString.Substring(0, end1) + "\n"; - } else if (counter == 1) { - hudString = hudString.Substring(end1 + 1, end2 - end1); - // Temporary fix, should add a new CustomOption for spaces - int gap = 2; - int index = hudString.TakeWhile(c => (gap -= (c == '\n' ? 1 : 0)) > 0).Count(); - hudString = hudString.Insert(index, "\n"); - gap = 7; - index = hudString.TakeWhile(c => (gap -= (c == '\n' ? 1 : 0)) > 0).Count(); - hudString = hudString.Insert(index + 1, "\n"); - gap = 11; - index = hudString.TakeWhile(c => (gap -= (c == '\n' ? 1 : 0)) > 0).Count(); - hudString = hudString.Insert(index + 1, "\n"); - } else if (counter == 2) { - hudString = hudString.Substring(end2 + 1); - } - hudString += "\n Press tab for more...\n\n\n"; - __result = hudString; - } - } - - [HarmonyPatch(typeof(GameSettingMenu), "OnEnable")] - class GameSettingMenuPatch { - public static void Prefix(GameSettingMenu __instance) { - __instance.HideForOnline = new Transform[]{}; - } - } -} \ No newline at end of file diff --git a/Source Code/Garlic.cs b/Source Code/Garlic.cs index d2f6f6a..e47b3e0 100644 --- a/Source Code/Garlic.cs +++ b/Source Code/Garlic.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Generic; using System.Collections; using UnityEngine; -using static TheOtherRoles.TheOtherRoles; namespace TheOtherRoles{ class Garlic { @@ -57,7 +56,7 @@ namespace TheOtherRoles{ public void Update() { if (background != null) - background.transform.Rotate(Vector3.forward * 6 * Time.deltaTime); + background.transform.Rotate(Vector3.forward * 6 * Time.fixedDeltaTime); } } } \ No newline at end of file diff --git a/Source Code/Helpers.cs b/Source Code/Helpers.cs index b6ad461..4833e39 100644 --- a/Source Code/Helpers.cs +++ b/Source Code/Helpers.cs @@ -2,28 +2,31 @@ using System; using System.Collections.Generic; using System.IO; using System.Reflection; -using Reactor.Extensions; using System.Collections; -using Reactor.Unstrip; using UnhollowerBaseLib; using UnityEngine; +using System.Linq; using static TheOtherRoles.TheOtherRoles; using HarmonyLib; using Hazel; +using TaskTypes = CBFIAGIGOFA; + namespace TheOtherRoles { public static class Helpers { - public static Sprite LoadSpriteFromEmbeddedResources(string resource, float PixelPerUnit) { + public static Sprite loadSpriteFromResources(string path, float pixelsPerUnit) { try { - System.Reflection.Assembly myAssembly = System.Reflection.Assembly.GetExecutingAssembly(); - System.IO.Stream myStream = myAssembly.GetManifestResourceStream(resource); - byte[] image = new byte[myStream.Length]; - myStream.Read(image, 0, (int) myStream.Length); - Texture2D myTexture = new Texture2D(2, 2, TextureFormat.ARGB32, true); - LoadImage(myTexture, image, true); - return Sprite.Create(myTexture, new Rect(0, 0, myTexture.width, myTexture.height), new Vector2(0.5f, 0.5f), PixelPerUnit); - } catch { } + Texture2D texture = new Texture2D(2, 2, TextureFormat.ARGB32, true); + Assembly assembly = Assembly.GetExecutingAssembly(); + Stream stream = assembly.GetManifestResourceStream(path); + var byteTexture = new byte[stream.Length]; + var read = stream.Read(byteTexture, 0, (int) stream.Length); + LoadImage(texture, byteTexture, false); + return Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0.5f, 0.5f), pixelsPerUnit); + } catch { + System.Console.WriteLine("Error loading sprite from path: " + path); + } return null; } @@ -38,22 +41,6 @@ namespace TheOtherRoles { return iCall_LoadImage.Invoke(tex.Pointer, il2cppArray.Pointer, markNonReadable); } - public static int a = 0; - - public static Sprite loadSpriteFromResources(string path, float pixelsPerUnit) { - try { - Texture2D texture = GUIExtensions.CreateEmptyTexture(); - Assembly assembly = Assembly.GetExecutingAssembly(); - Stream stream = assembly.GetManifestResourceStream(path); - byte[] byteTexture = Reactor.Extensions.Extensions.ReadFully(stream); - ImageConversion.LoadImage(texture, byteTexture, false); - return Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0.5f, 0.5f), pixelsPerUnit); - } catch { - System.Console.WriteLine("Error loading sprite from path: " + path); - } - return null; - } - public static PlayerControl playerById(byte id) { foreach (PlayerControl player in PlayerControl.AllPlayerControls) @@ -70,14 +57,14 @@ namespace TheOtherRoles { return res; } - public static void setSkinWithAnim(PlayerPhysics playerPhysics, uint skinId) { - SkinData nextSkin = DestroyableSingleton.Instance.AllSkins[(int)skinId]; + public static void setSkinWithAnim(PlayerPhysics playerPhysics, uint LFDAHOFPIAM) { + SkinData nextSkin = DestroyableSingleton.CMJOLNCMAPD.AllSkins[(int)LFDAHOFPIAM]; AnimationClip clip = null; var spriteAnim = playerPhysics.Skin.animator; var anim = spriteAnim.m_animator; var skinLayer = playerPhysics.Skin; - var currentPhysicsAnim = playerPhysics.Animator.GetCurrentAnimation(); + var currentPhysicsAnim = playerPhysics.NDIJGONKPMC.GetCurrentAnimation(); if (currentPhysicsAnim == playerPhysics.RunAnim) clip = nextSkin.RunAnim; else if (currentPhysicsAnim == playerPhysics.SpawnAnim) clip = nextSkin.SpawnAnim; else if (currentPhysicsAnim == playerPhysics.EnterVentAnim) clip = nextSkin.EnterVentAnim; @@ -85,7 +72,7 @@ namespace TheOtherRoles { else if (currentPhysicsAnim == playerPhysics.IdleAnim) clip = nextSkin.IdleAnim; else clip = nextSkin.IdleAnim; - float progress = playerPhysics.Animator.m_animator.GetCurrentAnimatorStateInfo(0).normalizedTime; + float progress = playerPhysics.NDIJGONKPMC.m_animator.GetCurrentAnimatorStateInfo(0).normalizedTime; skinLayer.skin = nextSkin; spriteAnim.Play(clip, 1f); @@ -93,30 +80,11 @@ namespace TheOtherRoles { anim.Update(0f); } - public static IEnumerator CoFlashAndDisable(SpriteRenderer renderer, float duration, Color a, Color b) { - float singleDuration = duration / 2; - for (float t = 0f; t < singleDuration; t += Time.deltaTime) { - if (renderer != null) - renderer.color = Color.Lerp(a, b, Mathf.Clamp(t / singleDuration, 0, 1)); - yield return null; - } - for (float t = singleDuration; t > 0f; t -= Time.deltaTime) { - if (renderer != null) - renderer.color = Color.Lerp(a, b, Mathf.Clamp(t / singleDuration, 0, 1)); - yield return null; - } - - if (renderer != null) renderer.enabled = false; - } - - - public static bool handleMurderAttempt(PlayerControl target, bool notifyOthers = true) { + public static bool handleMurderAttempt(PlayerControl target, bool isMeetingStart = false) { // Block impostor shielded kill if (Medic.shielded != null && Medic.shielded == target) { - if (notifyOthers) { - MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.ShieldedMurderAttempt, Hazel.SendOption.Reliable, -1); - AmongUsClient.Instance.FinishRpcImmediately(writer); - } + MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.ShieldedMurderAttempt, Hazel.SendOption.Reliable, -1); + AmongUsClient.Instance.FinishRpcImmediately(writer); RPCProcedure.shieldedMurderAttempt(); return false; @@ -125,20 +93,30 @@ namespace TheOtherRoles { else if (Child.child != null && target == Child.child && !Child.isGrownUp()) { return false; } + // Block Time Master with time shield kill + else if (TimeMaster.shieldActive && TimeMaster.timeMaster != null && TimeMaster.timeMaster == target) { + if (!isMeetingStart) { // Only rewind the attempt was not called because a meeting startet + MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.TimeMasterRewindTime, Hazel.SendOption.Reliable, -1); + AmongUsClient.Instance.FinishRpcImmediately(writer); + RPCProcedure.timeMasterRewindTime(); + } + return false; + } return true; } - public static void removeTasksFromPlayer(PlayerControl player, bool removeImportantTextTasks = false) { + public static void removeTasksFromPlayer(PlayerControl player) { if (player == null) return; var toRemove = new List(); foreach (PlayerTask task in player.myTasks) { - if (!removeImportantTextTasks && task.gameObject.GetComponent() != null) + if (task.gameObject.GetComponent() != null) continue; if (task.TaskType != TaskTypes.FixComms && task.TaskType != TaskTypes.FixLights && task.TaskType != TaskTypes.ResetReactor && task.TaskType != TaskTypes.ResetSeismic && - task.TaskType != TaskTypes.RestoreOxy) { + task.TaskType != TaskTypes.RestoreOxy && + task.TaskType != TaskTypes.StopCharles) { toRemove.Add(task); } } @@ -147,22 +125,48 @@ namespace TheOtherRoles { } } - public static IEnumerator Slide2D(Transform target, Vector2 source, Vector2 dest, float duration = 0.75f) - { - Vector3 temp = default(Vector3); - temp.z = target.localPosition.z; - for (float time = 0f; time < duration; time += Time.deltaTime) - { - float num = time / duration; - temp.x = Mathf.SmoothStep(source.x, dest.x, num); - temp.y = Mathf.SmoothStep(source.y, dest.y, num); - target.localPosition = temp; - yield return null; + public static void refreshRoleDescription(PlayerControl player) { + if (player == null) return; + + List infos = RoleInfo.getRoleInfoForPlayer(player); + + var toRemove = new List(); + foreach (PlayerTask t in player.myTasks) { + var textTask = t.gameObject.GetComponent(); + if (textTask != null) { + var info = infos.FirstOrDefault(x => textTask.Text.StartsWith(x.name)); + if (info != null) + infos.Remove(info); // TextTask for this RoleInfo does not have to be added, as it already exists + else + toRemove.Add(t); // TextTask does not have a corresponding RoleInfo and will hence be deleted + } + } + + foreach (PlayerTask t in toRemove) { + t.OnRemove(); + player.myTasks.Remove(t); + UnityEngine.Object.Destroy(t.gameObject); } - temp.x = dest.x; - temp.y = dest.y; - target.localPosition = temp; - yield break; + + // Add TextTask for remaining RoleInfos + foreach (RoleInfo roleInfo in infos) { + var task = new GameObject("RoleTask").AddComponent(); + task.transform.SetParent(player.transform, false); + + if (roleInfo.name == "Jackal") { + var getSidekickText = Jackal.canCreateSidekick ? " and recruit a Sidekick" : ""; + task.Text = $"{roleInfo.colorHexString()}{roleInfo.name}: Kill everyone{getSidekickText}"; + } else { + task.Text = $"{roleInfo.colorHexString()}{roleInfo.name}: {roleInfo.shortDescription}"; + } + + player.myTasks.Insert(0, task); + } + } + + private static List lighterColors = new List(){ 3, 4, 5, 7, 10, 11}; + public static bool isLighterColor(int colorId) { + return lighterColors.Contains(colorId); } } } \ No newline at end of file diff --git a/Source Code/IntroPatch.cs b/Source Code/IntroPatch.cs index 0418beb..62581c5 100644 --- a/Source Code/IntroPatch.cs +++ b/Source Code/IntroPatch.cs @@ -2,25 +2,21 @@ using HarmonyLib; using System; using static TheOtherRoles.TheOtherRoles; using UnityEngine; - +using System.Collections.Generic; namespace TheOtherRoles { - [HarmonyPatch(typeof(IntroCutscene.CoBegin__d), nameof(IntroCutscene.CoBegin__d.MoveNext))] + [HarmonyPatch(typeof(IntroCutscene.MDIMNFHLFBN), nameof(IntroCutscene.MDIMNFHLFBN.MoveNext))] class IntroPatch { // Intro special teams - static void Prefix(IntroCutscene.CoBegin__d __instance) + static void Prefix(IntroCutscene.MDIMNFHLFBN __instance) { if (PlayerControl.LocalPlayer == Jester.jester) { var jesterTeam = new Il2CppSystem.Collections.Generic.List(); jesterTeam.Add(PlayerControl.LocalPlayer); __instance.yourTeam = jesterTeam; - } else if (PlayerControl.LocalPlayer == Shifter.shifter) { - var shifterTeam = new Il2CppSystem.Collections.Generic.List(); - shifterTeam.Add(PlayerControl.LocalPlayer); - __instance.yourTeam = shifterTeam; } else if (PlayerControl.LocalPlayer == Jackal.jackal) { var jackalTeam = new Il2CppSystem.Collections.Generic.List(); jackalTeam.Add(PlayerControl.LocalPlayer); @@ -29,33 +25,35 @@ namespace TheOtherRoles } // Intro display role - static void Postfix(IntroCutscene.CoBegin__d __instance) + static void Postfix(IntroCutscene.MDIMNFHLFBN __instance) { - RoleInfo roleInfo = RoleInfo.getRoleInfoForPlayer(PlayerControl.LocalPlayer); + List infos = RoleInfo.getRoleInfoForPlayer(PlayerControl.LocalPlayer); + if (infos.Count == 0) return; + RoleInfo roleInfo = infos[0]; if (PlayerControl.LocalPlayer == Lovers.lover1 || PlayerControl.LocalPlayer == Lovers.lover2) { PlayerControl otherLover = PlayerControl.LocalPlayer == Lovers.lover1 ? Lovers.lover2 : Lovers.lover1; - __instance.__this.Title.Text = PlayerControl.LocalPlayer.Data.IsImpostor ? "[FF1919FF]Imp[FC03BEFF]Lover" : "Lover"; - __instance.__this.Title.Color = PlayerControl.LocalPlayer.Data.IsImpostor ? Color.white : Lovers.color; - __instance.__this.ImpostorText.Text = "You are in [FC03BEFF]Love [FFFFFFFF] with [FC03BEFF]" + (otherLover?.Data?.PlayerName ?? ""); - __instance.__this.ImpostorText.gameObject.SetActive(true); - __instance.__this.BackgroundBar.material.color = Lovers.color; + __instance.__4__this.Title.Text = PlayerControl.LocalPlayer.IDOFAMCIJKE.CIDDOFDJHJH ? "[FF1919FF]Imp[FC03BEFF]Lover" : "Lover"; + __instance.__4__this.Title.Color = PlayerControl.LocalPlayer.IDOFAMCIJKE.CIDDOFDJHJH ? Color.white : Lovers.color; + __instance.__4__this.ImpostorText.Text = "You are in [FC03BEFF]Love [FFFFFFFF] with [FC03BEFF]" + (otherLover?.IDOFAMCIJKE?.HGGCLJHCDBM ?? ""); + __instance.__4__this.ImpostorText.gameObject.SetActive(true); + __instance.__4__this.BackgroundBar.material.color = Lovers.color; } else if (PlayerControl.LocalPlayer == BountyHunter.bountyHunter) { - __instance.__this.Title.Text = "Bounty Hunter"; - __instance.__this.Title.Color = BountyHunter.color; - __instance.__this.ImpostorText.Text = "Hunt [ED653BFF]" + BountyHunter.target?.Data?.PlayerName + "[FFFFFFFF] down"; - __instance.__this.BackgroundBar.material.color = BountyHunter.color; + __instance.__4__this.Title.Text = "Bounty Hunter"; + __instance.__4__this.Title.Color = BountyHunter.color; + __instance.__4__this.ImpostorText.Text = "Hunt [ED653BFF]" + BountyHunter.target?.IDOFAMCIJKE?.HGGCLJHCDBM + "[FFFFFFFF] down"; + __instance.__4__this.BackgroundBar.material.color = BountyHunter.color; } else if (roleInfo.name == "Crewmate" || roleInfo.name == "Impostor") {} else { - __instance.__this.Title.Text = roleInfo.name; - __instance.__this.Title.Color = roleInfo.color; - __instance.__this.ImpostorText.gameObject.SetActive(true); - __instance.__this.ImpostorText.Text = roleInfo.introDescription; - __instance.__this.BackgroundBar.material.color = roleInfo.color; + __instance.__4__this.Title.Text = roleInfo.name; + __instance.__4__this.Title.Color = roleInfo.color; + __instance.__4__this.ImpostorText.gameObject.SetActive(true); + __instance.__4__this.ImpostorText.Text = roleInfo.introDescription; + __instance.__4__this.BackgroundBar.material.color = roleInfo.color; } } } diff --git a/Source Code/Main.cs b/Source Code/Main.cs index 5114366..b9109bd 100644 --- a/Source Code/Main.cs +++ b/Source Code/Main.cs @@ -3,9 +3,7 @@ using BepInEx.Configuration; using BepInEx.IL2CPP; using HarmonyLib; using Hazel; -using Reactor; using System.Collections.Generic; -using Essentials.Options; using System.Linq; using System.Net; using System.IO; @@ -17,198 +15,29 @@ using static TheOtherRoles.TheOtherRoles; namespace TheOtherRoles { - [BepInPlugin(Id)] + [BepInPlugin(Id, "The Other Roles", "2.0.0")] [BepInProcess("Among Us.exe")] - [BepInDependency(ReactorPlugin.Id)] public class TheOtherRolesPlugin : BasePlugin { public const string Id = "me.eisbison.theotherroles"; public Harmony Harmony { get; } = new Harmony(Id); - public static TheOtherRolesPlugin Instance { get { return PluginSingleton.Instance; } } - internal static BepInEx.Logging.ManualLogSource Logger { get { return Instance.Log; } } + public static TheOtherRolesPlugin Instance; - // Roles - public static int num = 0; - public static string[] rates = new string[]{"0%", "10%", "20%", "30%", "40%", "50%", "60%", "70%", "80%", "90%", "100%"}; - public static string[] crewmateRoleCaps = new string[]{"0", "0-1", "1", "1-2", "2", "2-3", "3", "3-4", "4", "4-5", "5", "5-6", "6", "6-7", "7", "7-8", "8", "8-9", "9", "9-10", "10"}; - public static string[] impostorRoleCaps = new string[]{"0", "0-1", "1", "1-2", "2", "2-3", "3"}; - - public static CustomStringOption crewmateRolesCount = CustomOption.AddString(num++.ToString(), "[CCCC00FF]Number Of Crewmate/Neutral Roles", crewmateRoleCaps); - public static CustomStringOption impostorRolesCount = CustomOption.AddString(num++.ToString(), "[CCCC00FF]Number Of Impostor Roles", impostorRoleCaps); - - public static CustomStringOption mafiaSpawnRate = CustomOption.AddString(num++.ToString(), cs(Janitor.color) + "Mafia", rates); - public static CustomStringOption morphlingSpawnRate = CustomOption.AddString(num++.ToString(), cs(Morphling.color) + "Morphling", rates); - public static CustomStringOption camouflagerSpawnRate = CustomOption.AddString(num++.ToString(), cs(Camouflager.color) + "Camouflager", rates); - public static CustomStringOption vampireSpawnRate = CustomOption.AddString(num++.ToString(), cs(Vampire.color) + "Vampire", rates); - - public static CustomStringOption loversSpawnRate = CustomOption.AddString(num++.ToString(), cs(Lovers.color) + "Lovers", rates); - public static CustomStringOption jesterSpawnRate = CustomOption.AddString(num++.ToString(), cs(Jester.color) + "Jester", rates); - public static CustomStringOption shifterSpawnRate = CustomOption.AddString(num++.ToString(), cs(Shifter.color) + "Shifter", rates); - - public static CustomStringOption mayorSpawnRate = CustomOption.AddString(num++.ToString(), cs(Mayor.color) + "Mayor", rates); - public static CustomStringOption engineerSpawnRate = CustomOption.AddString(num++.ToString(), cs(Engineer.color) + "Engineer", rates); - public static CustomStringOption sheriffSpawnRate = CustomOption.AddString(num++.ToString(), cs(Sheriff.color) + "Sheriff", rates); - public static CustomStringOption lighterSpawnRate = CustomOption.AddString(num++.ToString(), cs(Lighter.color) + "Lighter", rates); - public static CustomStringOption detectiveSpawnRate = CustomOption.AddString(num++.ToString(), cs(Detective.color) + "Detective", rates); - public static CustomStringOption timeMasterSpawnRate = CustomOption.AddString(num++.ToString(), cs(TimeMaster.color) + "Time Master", rates); - public static CustomStringOption medicSpawnRate = CustomOption.AddString(num++.ToString(), cs(Medic.color) + "Medic", rates); - public static CustomStringOption swapperSpawnRate = CustomOption.AddString(num++.ToString(), cs(Swapper.color) + "Swapper", rates); - public static CustomStringOption seerSpawnRate = CustomOption.AddString(num++.ToString(), cs(Seer.color) + "Seer", rates); - public static CustomStringOption spySpawnRate = CustomOption.AddString(num++.ToString(), cs(Spy.color) + "Spy", rates); - public static CustomStringOption childSpawnRate = CustomOption.AddString(num++.ToString(), cs(Child.color) + "Child", rates); - // public static CustomStringOption bountyHunterSpawnRate = CustomOption.AddString(num++.ToString(), cs(BountyHunter.color) + "Bounty Hunter", rates); - public static CustomStringOption trackerSpawnRate = CustomOption.AddString(num++.ToString(), cs(Tracker.color) + "Tracker", rates); - public static CustomStringOption snitchSpawnRate = CustomOption.AddString(num++.ToString(), cs(Snitch.color) + "Snitch", rates); - public static CustomStringOption jackalSpawnRate = CustomOption.AddString(num++.ToString(), cs(Jackal.color) + "Jackal", rates); - - // Role settings - public static CustomNumberOption janitorCooldown = CustomOption.AddNumber(num++.ToString(), "Janitor Cooldown", 30f, 10f, 60f, 2.5f); - public static CustomNumberOption morphlingCooldown = CustomOption.AddNumber(num++.ToString(), "Morphling Cooldown", 30f, 10f, 60f, 2.5f); - public static CustomNumberOption camouflagerCooldown = CustomOption.AddNumber(num++.ToString(), "Camouflager Cooldown", 30f, 10f, 60f, 2.5f); - public static CustomNumberOption vampireKillDelay = CustomOption.AddNumber(num++.ToString(), "Vampire Kill Delay", 10f, 1f, 20f, 1f); - public static CustomNumberOption vampireCooldown = CustomOption.AddNumber(num++.ToString(), "Vampire Cooldown", 30f, 10f, 60f, 2.5f); - public static CustomToggleOption vampireCanKillNearGarlics = CustomOption.AddToggle(num++.ToString(), "Vampire Can Kill Near Garlics", true); - - public static CustomNumberOption loversImpLoverRate = CustomOption.AddNumber(num++.ToString(), "Chance That One Lover Is Impostor", 30f, 0f, 100f, 10f); - public static CustomToggleOption loversBothDie = CustomOption.AddToggle(num++.ToString(), "Both Lovers Die", true); - public static CustomNumberOption shifterCooldown = CustomOption.AddNumber(num++.ToString(), "Shifter Cooldown", 30f, 10f, 60f, 2.5f); - - public static CustomNumberOption sheriffCooldown = CustomOption.AddNumber(num++.ToString(), "Sheriff Cooldown", 30f, 10f, 60f, 2.5f); - public static CustomToggleOption jesterCanDieToSheriff = CustomOption.AddToggle(num++.ToString(), "Jester Can Die To Sheriff", false); - public static CustomNumberOption lighterVision = CustomOption.AddNumber(num++.ToString(), "Lighter Vision", 2f, 0.25f, 5f, 0.25f); - public static CustomToggleOption detectiveAnonymousFootprints = CustomOption.AddToggle(num++.ToString(), "Anonymous Footprints", false); - public static CustomNumberOption detectiveFootprintIntervall = CustomOption.AddNumber(num++.ToString(), "Footprint Intervall", 0.5f, 0.25f, 10f, 0.25f); - public static CustomNumberOption detectiveFootprintDuration = CustomOption.AddNumber(num++.ToString(), "Footprint Duration", 5f, 0.25f, 10f, 0.25f); - public static CustomNumberOption timeMasterCooldown = CustomOption.AddNumber(num++.ToString(), "Time Master Cooldown", 30f, 10f, 60f, 2.5f); - public static CustomNumberOption timeMasterRewindTime = CustomOption.AddNumber(num++.ToString(), "Rewind Time", 3f, 1f, 10f, 1f); - public static CustomToggleOption timeMasterReviveDuringRewind = CustomOption.AddToggle(num++.ToString(), "Revive During Rewind", false); - public static CustomNumberOption medicReportNameDuration = CustomOption.AddNumber(num++.ToString(), "Time Where Medic Reports Will Have Name", 10, 0, 60, 2.5f); - public static CustomNumberOption medicReportColorDuration = CustomOption.AddNumber(num++.ToString(), "Time Where Medic Reports Will Have Color Type", 20, 0, 120, 2.5f); - public static CustomStringOption medicShowShielded = CustomOption.AddString(num++.ToString(), "Show Shielded Player", new string[] {"Everyone", "Shielded + Medic", "Medic"}); - public static CustomToggleOption medicShowAttemptToShielded = CustomOption.AddToggle(num++.ToString(), "Shielded Player Sees Murder Attempt", false); - public static CustomNumberOption seerCooldown = CustomOption.AddNumber(num++.ToString(), "Seer Cooldown (No Reset After Meeting)", 15f, 30f, 180f, 15f); - public static CustomNumberOption seerChanceOfSeeingRight = CustomOption.AddNumber(num++.ToString(), "Seer Chance Of Seeing Right", 100, 0, 100, 5); - public static CustomStringOption seerKindOfInfo = CustomOption.AddString(num++.ToString(), "Info That Seer Reveals", new string[] {"Role", "Good/Bad"}); - public static CustomStringOption seerPlayersWithNotification = CustomOption.AddString(num++.ToString(), "Players That See When They Are Being Revealed", new string[] {"Everyone", "The Good", "The Bad", "Nobody"}); - public static CustomNumberOption spyCooldown = CustomOption.AddNumber(num++.ToString(), "Spy Cooldown", 30f, 10f, 120f, 5f); - public static CustomNumberOption spySpyingDuration = CustomOption.AddNumber(num++.ToString(), "Spy Duration", 10f, 2.5f, 60f, 2.5f); - public static CustomNumberOption childGrowingUpDuration = CustomOption.AddNumber(num++.ToString(), "Child Growing Up Duration", 400f, 100f, 1500f, 100f); - // public static CustomToggleOption bountyHunterNotifyBounty = CustomOption.AddToggle(num++.ToString(), "Bounty Gets Notified", true); - public static CustomNumberOption trackerUpdateIntervall = CustomOption.AddNumber(num++.ToString(), "Tracker Update Intervall", 5f, 2.5f, 30f, 2.5f); - public static CustomNumberOption snitchLeftTasksForImpostors = CustomOption.AddNumber(num++.ToString(), "Task Count Where Impostors See Snitch", 1f, 0f, 5f, 1f); - - public static CustomNumberOption jackalKillCooldown = CustomOption.AddNumber(num++.ToString(), "Jackal/Sidekick Kill Cooldown", 30f, 10f, 60f, 2.5f); - public static CustomNumberOption jackalCreateSidekickCooldown = CustomOption.AddNumber(num++.ToString(), "Jackal Create Sidekick Cooldown", 30f, 10f, 60f, 2.5f); - public static CustomToggleOption jackalCanUseVents = CustomOption.AddToggle(num++.ToString(), "Jackal can use vents", true); - public static CustomToggleOption jackalCanCreateSidekick = CustomOption.AddToggle(num++.ToString(), "Jackal can create a sidekick", false); - public static CustomToggleOption sidekickPromotesToJackal = CustomOption.AddToggle(num++.ToString(), "Sidekick gets promoted to Jackal on Jackal death", false); - public static CustomToggleOption sidekickCanKill = CustomOption.AddToggle(num++.ToString(), "Sidekick can kill", false); - public static CustomToggleOption sidekickCanUseVents = CustomOption.AddToggle(num++.ToString(), "Sidekick can use vents", true); - public static CustomToggleOption jackalPromotedFromSidekickCanCreateSidekick = CustomOption.AddToggle(num++.ToString(), "Jackals promoted from Sidekick can create a Sidekick", true); - public static CustomToggleOption jackalCanCreateSidekickFromImpostor = CustomOption.AddToggle(num++.ToString(), "Jackals can make an Impostor to his Sidekick", true); - - - public static List options = new List(); public static int optionsPage = 1; public static ConfigEntry DebugMode { get; private set; } public override void Load() { - DebugMode = Config.Bind("Custom", "Enable Debug Mode", false); + DebugMode = Config.Bind("Custom", "Enable Debug Mode", false); + Instance = this; + CustomOptionHolder.Load(); - CustomOption.ShamelessPlug = false; Harmony.PatchAll(); } - - public static string cs(Color c) { - return string.Format("[{0:X2}{1:X2}{2:X2}{3:X2}]", ToByte(c.r), ToByte(c.g), ToByte(c.b), ToByte(c.a)); - } - - private static byte ToByte(float f) { - f = Mathf.Clamp01(f); - return (byte)(f * 255); - } - - public TheOtherRolesPlugin() { - options = new List() { - crewmateRolesCount, - impostorRolesCount, - - mafiaSpawnRate, - morphlingSpawnRate, - camouflagerSpawnRate, - vampireSpawnRate, - - loversSpawnRate, - jesterSpawnRate, - shifterSpawnRate, - - mayorSpawnRate, - engineerSpawnRate, - sheriffSpawnRate, - lighterSpawnRate, - detectiveSpawnRate, - timeMasterSpawnRate, - medicSpawnRate, - swapperSpawnRate, - seerSpawnRate, - spySpawnRate, - childSpawnRate, - // bountyHunterSpawnRate, - trackerSpawnRate, - snitchSpawnRate, - jackalSpawnRate, - - janitorCooldown, - morphlingCooldown, - camouflagerCooldown, - vampireKillDelay, - vampireCooldown, - vampireCanKillNearGarlics, - - loversImpLoverRate, - loversBothDie, - shifterCooldown, - - sheriffCooldown, - jesterCanDieToSheriff, - lighterVision, - detectiveAnonymousFootprints, - detectiveFootprintIntervall, - detectiveFootprintDuration, - timeMasterCooldown, - timeMasterRewindTime, - timeMasterReviveDuringRewind, - medicReportNameDuration, - medicReportColorDuration, - medicShowShielded, - medicShowAttemptToShielded, - seerCooldown, - seerChanceOfSeeingRight, - seerKindOfInfo, - seerPlayersWithNotification, - spyCooldown, - spySpyingDuration, - childGrowingUpDuration, - // bountyHunterNotifyBounty, - trackerUpdateIntervall, - snitchLeftTasksForImpostors, - - jackalKillCooldown, - jackalCreateSidekickCooldown, - jackalCanUseVents, - jackalCanCreateSidekick, - sidekickPromotesToJackal, - sidekickCanKill, - sidekickCanUseVents, - jackalPromotedFromSidekickCanCreateSidekick, - jackalCanCreateSidekickFromImpostor - }; - } } // Deactivate bans, since I always leave my local testing game and ban myself - [HarmonyPatch(typeof(StatsManager), nameof(StatsManager.AmBanned), MethodType.Getter)] + [HarmonyPatch(typeof(MOJBJJPEFPG), nameof(MOJBJJPEFPG.IJMECJONBHM), MethodType.Getter)] public static class AmBannedPatch { public static void Postfix(out bool __result) @@ -235,16 +64,16 @@ namespace TheOtherRoles bots.Add(playerControl); GameData.Instance.AddPlayer(playerControl); - AmongUsClient.Instance.Spawn(playerControl, -2, SpawnFlags.None); + AmongUsClient.Instance.Spawn(playerControl, -2, EOCEBECJBHG.None); playerControl.transform.position = PlayerControl.LocalPlayer.transform.position; playerControl.GetComponent().enabled = true; playerControl.NetTransform.enabled = false; playerControl.SetName(RandomString(10)); - playerControl.SetColor((byte) random.Next(Palette.PlayerColors.Length)); - playerControl.SetHat((uint) random.Next(HatManager.Instance.AllHats.Count),playerControl.Data.ColorId); - playerControl.SetPet((uint) random.Next(HatManager.Instance.AllPets.Count)); - playerControl.SetSkin((uint) random.Next(HatManager.Instance.AllSkins.Count)); + playerControl.SetColor((byte) random.Next(GLNPIJPGGNJ.CALCLMEEPGL.Length)); + playerControl.SetHat((uint) random.Next(HatManager.CMJOLNCMAPD.AllHats.Count), playerControl.IDOFAMCIJKE.JFHFMIKFHGG); + playerControl.SetPet((uint) random.Next(HatManager.CMJOLNCMAPD.AllPets.Count)); + playerControl.SetSkin((uint) random.Next(HatManager.CMJOLNCMAPD.AllSkins.Count)); GameData.Instance.RpcSetTasks(playerControl.PlayerId, new byte[0]); } diff --git a/Source Code/MapOptions.cs b/Source Code/MapOptions.cs new file mode 100644 index 0000000..d10d853 --- /dev/null +++ b/Source Code/MapOptions.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; +using System.Collections; +using System; +using UnityEngine; +using static TheOtherRoles.TheOtherRoles; + +namespace TheOtherRoles{ + static class MapOptions { + // Set values + public static int maxNumberOfMeetings = 10; + + // Updating values + public static int meetingsCount = 0; + + public static void clearAndReloadMapOptions() { + meetingsCount = 0; + + maxNumberOfMeetings = Mathf.RoundToInt(CustomOptionHolder.maxNumberOfMeetings.getSelection()); + } + } +} \ No newline at end of file diff --git a/Source Code/MeetingPatch.cs b/Source Code/MeetingPatch.cs index 5a01785..3d079bd 100644 --- a/Source Code/MeetingPatch.cs +++ b/Source Code/MeetingPatch.cs @@ -8,26 +8,29 @@ using System.Collections; using System; using System.Text; using UnityEngine; +using System.Reflection; + +using Effects = HLPCBNMDEHF; +using Palette = GLNPIJPGGNJ; namespace TheOtherRoles { - [HarmonyPatch(typeof(MeetingHud), "CalculateVotes")] + [HarmonyPatch(typeof(MeetingHud), nameof(MeetingHud.CDLGIAMFHBH))] class MeetingCalculateVotesPatch { - static bool Prefix(MeetingHud __instance, ref Il2CppStructArray __result) - { - Il2CppStructArray array = new Il2CppStructArray(11); - for (int i = 0; i < __instance.playerStates.Length; i++) + private static byte[] calculateVotes(MeetingHud __instance) { + byte[] array = new byte[11]; + for (int i = 0; i < __instance.DHCOPOOJCLN.Length; i++) { - PlayerVoteArea playerVoteArea = __instance.playerStates[i]; + PlayerVoteArea playerVoteArea = __instance.DHCOPOOJCLN[i]; if (playerVoteArea.didVote) { int num = (int)(playerVoteArea.votedFor + 1); if (num >= 0 && num < array.Length) { - Il2CppStructArray array2 = array; + byte[] array2 = array; int num2 = num; // Mayor count vote twice - if (Mayor.mayor != null && playerVoteArea.TargetPlayerId == (sbyte)Mayor.mayor.PlayerId) + if (Mayor.mayor != null && playerVoteArea.HMPHKKGPLAG == (sbyte)Mayor.mayor.PlayerId) array2[num2] += 2; else array2[num2] += 1; @@ -39,99 +42,152 @@ namespace TheOtherRoles PlayerVoteArea swapped1 = null; PlayerVoteArea swapped2 = null; - foreach (PlayerVoteArea playerVoteArea in __instance.playerStates) { - if (playerVoteArea.TargetPlayerId == Swapper.playerId1) swapped1 = playerVoteArea; - if (playerVoteArea.TargetPlayerId == Swapper.playerId2) swapped2 = playerVoteArea; + foreach (PlayerVoteArea playerVoteArea in __instance.DHCOPOOJCLN) { + if (playerVoteArea.HMPHKKGPLAG == Swapper.playerId1) swapped1 = playerVoteArea; + if (playerVoteArea.HMPHKKGPLAG == Swapper.playerId2) swapped2 = playerVoteArea; } - if (swapped1 != null && swapped2 != null && swapped1.TargetPlayerId + 1 >= 0 && swapped1.TargetPlayerId + 1 < array.Length && swapped2.TargetPlayerId + 1 >= 0 && swapped2.TargetPlayerId + 1 < array.Length) { - byte tmp = array[swapped1.TargetPlayerId + 1]; - array[swapped1.TargetPlayerId + 1] = array[swapped2.TargetPlayerId + 1]; - array[swapped2.TargetPlayerId + 1] = tmp; + if (swapped1 != null && swapped2 != null && swapped1.HMPHKKGPLAG + 1 >= 0 && swapped1.HMPHKKGPLAG + 1 < array.Length && swapped2.HMPHKKGPLAG + 1 >= 0 && swapped2.HMPHKKGPLAG + 1 < array.Length) { + byte tmp = array[swapped1.HMPHKKGPLAG + 1]; + array[swapped1.HMPHKKGPLAG + 1] = array[swapped2.HMPHKKGPLAG + 1]; + array[swapped2.HMPHKKGPLAG + 1] = tmp; } + return array; + } - __result = array; + private static int IndexOfMax(byte[] self, Func comparer, out bool tie) { + tie = false; + int num = int.MinValue; + int result = -1; + for (int i = 0; i < self.Length; i++) + { + int num2 = comparer(self[i]); + if (num2 > num) + { + result = i; + num = num2; + tie = false; + } + else if (num2 == num) + { + tie = true; + result = -1; + } + } + return result; + } + + static bool Prefix(MeetingHud __instance) + { + if (__instance.DHCOPOOJCLN.All((PlayerVoteArea ps) => ps.isDead || ps.didVote)) + { + byte[] self = calculateVotes(__instance); + bool tie; + int maxIdx = IndexOfMax(self, (byte p) => (int)p, out tie) - 1; + GameData.OFKOJOKOOAK exiled = null; + foreach (GameData.OFKOJOKOOAK pi in GameData.Instance.AllPlayers) { + if (pi.GMBAIPNOKLP == maxIdx) { + exiled = pi; + break; + } + } + byte[] array = new byte[10]; + for (int i = 0; i < __instance.DHCOPOOJCLN.Length; i++) + { + PlayerVoteArea playerVoteArea = __instance.DHCOPOOJCLN[i]; + array[(int)playerVoteArea.HMPHKKGPLAG] = playerVoteArea.GetState(); + } + // RPCVotingComplete + if (AmongUsClient.Instance.HNMILJEOEKN) + __instance.MJIJGEBBMAO(array, exiled, tie); + MessageWriter messageWriter = AmongUsClient.Instance.StartRpc(__instance.NetId, 23, Hazel.SendOption.Reliable); + messageWriter.WriteBytesAndSize(array); + messageWriter.Write((exiled != null) ? exiled.GMBAIPNOKLP : byte.MaxValue); + messageWriter.Write(tie); + messageWriter.EndMessage(); + } return false; } } - [HarmonyPatch(typeof(MeetingHud), nameof(MeetingHud.PopulateResults))] + [HarmonyPatch(typeof(MeetingHud), nameof(MeetingHud.OMFOBKIENPI))] class MeetingPopulateVotesPatch { - static bool Prefix(MeetingHud __instance, Il2CppStructArray GNKPMAGJLNC) + static bool Prefix(MeetingHud __instance, Il2CppStructArray HIDHPMAKEKH) { // Swapper swap votes PlayerVoteArea swapped1 = null; PlayerVoteArea swapped2 = null; - foreach (PlayerVoteArea playerVoteArea in __instance.playerStates) { - if (playerVoteArea.TargetPlayerId == Swapper.playerId1) swapped1 = playerVoteArea; - if (playerVoteArea.TargetPlayerId == Swapper.playerId2) swapped2 = playerVoteArea; + foreach (PlayerVoteArea playerVoteArea in __instance.DHCOPOOJCLN) { + if (playerVoteArea.HMPHKKGPLAG == Swapper.playerId1) swapped1 = playerVoteArea; + if (playerVoteArea.HMPHKKGPLAG == Swapper.playerId2) swapped2 = playerVoteArea; } bool doSwap = swapped1 != null && swapped2 != null; if (doSwap) { - Reactor.Coroutines.Start(Helpers.Slide2D(swapped1.transform, swapped1.transform.localPosition, swapped2.transform.localPosition, 2f)); - Reactor.Coroutines.Start(Helpers.Slide2D(swapped2.transform, swapped2.transform.localPosition, swapped1.transform.localPosition, 2f)); + + __instance.StartCoroutine(Effects.NFAIFCPOFJK(swapped1.transform, swapped1.transform.localPosition, swapped2.transform.localPosition, 2f)); + __instance.StartCoroutine(Effects.NFAIFCPOFJK(swapped2.transform, swapped2.transform.localPosition, swapped1.transform.localPosition, 2f)); } // Mayor display vote twice - __instance.TitleText.Text = DestroyableSingleton.Instance.GetString(StringNames.MeetingVotingResults, new Il2CppReferenceArray(0)); + __instance.TitleText.Text = DestroyableSingleton.CMJOLNCMAPD.GetString(StringNames.MeetingVotingResults, new Il2CppReferenceArray(0)); int num = doSwap ? 4 : 0; // Delay animaton if swapping - for (int i = 0; i < __instance.playerStates.Length; i++) + for (int i = 0; i < __instance.DHCOPOOJCLN.Length; i++) { - PlayerVoteArea playerVoteArea = __instance.playerStates[i]; + PlayerVoteArea playerVoteArea = __instance.DHCOPOOJCLN[i]; playerVoteArea.ClearForResults(); int num2 = doSwap ? 4 : 0; // Delay animaton if swapping bool mayorFirstVoteDisplayed = false; - for (int j = 0; j < __instance.playerStates.Length; j++) + for (int j = 0; j < __instance.DHCOPOOJCLN.Length; j++) { - PlayerVoteArea playerVoteArea2 = __instance.playerStates[j]; - byte self = GNKPMAGJLNC[(int)playerVoteArea2.TargetPlayerId]; + PlayerVoteArea playerVoteArea2 = __instance.DHCOPOOJCLN[j]; + byte self = HIDHPMAKEKH[(int)playerVoteArea2.HMPHKKGPLAG]; if (!((self & 128) > 0)) { - GameData.PlayerInfo playerById = GameData.Instance.GetPlayerById((byte)playerVoteArea2.TargetPlayerId); + GameData.OFKOJOKOOAK playerById = GameData.Instance.GetPlayerById((byte)playerVoteArea2.HMPHKKGPLAG); int votedFor = (int)PlayerVoteArea.GetVotedFor(self); - if (votedFor == (int)playerVoteArea.TargetPlayerId) + if (votedFor == (int)playerVoteArea.HMPHKKGPLAG) { SpriteRenderer spriteRenderer = UnityEngine.Object.Instantiate(__instance.PlayerVotePrefab); - if (PlayerControl.GameOptions.AnonymousVotes) + if (PlayerControl.GameOptions.LNMFPEMGKOB) { - PlayerControl.SetPlayerMaterialColors(Palette.DisabledGrey, spriteRenderer); + PlayerControl.SetPlayerMaterialColors(Palette.JMELLHINKGM, spriteRenderer); } else { - PlayerControl.SetPlayerMaterialColors((int)playerById.ColorId, spriteRenderer); + PlayerControl.SetPlayerMaterialColors((int)playerById.JFHFMIKFHGG, spriteRenderer); } spriteRenderer.transform.SetParent(playerVoteArea.transform); - spriteRenderer.transform.localPosition = __instance.CounterOrigin + new Vector3(__instance.CounterOffsets.x * (float)num2, 0f, 0f); + spriteRenderer.transform.localPosition = __instance.ALGONDAMLHA + new Vector3(__instance.LKIOFMMBOBJ.x * (float)num2, 0f, 0f); spriteRenderer.transform.localScale = Vector3.zero; spriteRenderer.transform.SetParent(playerVoteArea.transform.parent); // Reparent votes so they don't move with their playerVoteArea - __instance.StartCoroutine(Effects.Bloop((float)num2 * 0.5f, spriteRenderer.transform, 1f, 0.5f)); + __instance.StartCoroutine(Effects.POFLJMGFBEJ((float)num2 * 0.5f, spriteRenderer.transform, 1f, 0.5f)); num2++; } else if (i == 0 && votedFor == -1) { SpriteRenderer spriteRenderer2 = UnityEngine.Object.Instantiate(__instance.PlayerVotePrefab); - if (PlayerControl.GameOptions.AnonymousVotes) + if (PlayerControl.GameOptions.LNMFPEMGKOB) { - PlayerControl.SetPlayerMaterialColors(Palette.DisabledGrey, spriteRenderer2); + PlayerControl.SetPlayerMaterialColors(Palette.JMELLHINKGM, spriteRenderer2); } else { - PlayerControl.SetPlayerMaterialColors((int)playerById.ColorId, spriteRenderer2); + PlayerControl.SetPlayerMaterialColors((int)playerById.JFHFMIKFHGG, spriteRenderer2); } spriteRenderer2.transform.SetParent(__instance.SkippedVoting.transform); - spriteRenderer2.transform.localPosition = __instance.CounterOrigin + new Vector3(__instance.CounterOffsets.x * (float)num, 0f, 0f); + spriteRenderer2.transform.localPosition = __instance.ALGONDAMLHA + new Vector3(__instance.LKIOFMMBOBJ.x * (float)num, 0f, 0f); spriteRenderer2.transform.localScale = Vector3.zero; spriteRenderer2.transform.SetParent(playerVoteArea.transform.parent); // Reparent votes so they don't move with their playerVoteArea - __instance.StartCoroutine(Effects.Bloop((float)num * 0.5f, spriteRenderer2.transform, 1f, 0.5f)); + __instance.StartCoroutine(Effects.POFLJMGFBEJ((float)num * 0.5f, spriteRenderer2.transform, 1f, 0.5f)); num++; } // Major vote, redo this iteration to place a second vote - if (Mayor.mayor != null && playerVoteArea2.TargetPlayerId == (sbyte)Mayor.mayor.PlayerId && !mayorFirstVoteDisplayed) { + if (Mayor.mayor != null && playerVoteArea2.HMPHKKGPLAG == (sbyte)Mayor.mayor.PlayerId && !mayorFirstVoteDisplayed) { mayorFirstVoteDisplayed = true; j--; } @@ -149,9 +205,9 @@ namespace TheOtherRoles static bool[] selections; static SpriteRenderer[] renderers; - [HarmonyPatch(typeof(MeetingHud), nameof(MeetingHud.VotingComplete))] + [HarmonyPatch(typeof(MeetingHud), nameof(MeetingHud.MJIJGEBBMAO))] class MeetingHudVotingCompletedPatch { - static void Postfix(MeetingHud __instance, byte[] GNKPMAGJLNC, GameData.PlayerInfo IHDMFDEEDEL, bool DCHFIBODGIL) + static void Postfix(MeetingHud __instance, byte[] HIDHPMAKEKH, GameData.OFKOJOKOOAK KLHCDCKJHKC, bool EMLKEPIBJLK) { // Reset swapper values Swapper.playerId1 = Byte.MaxValue; @@ -159,17 +215,17 @@ namespace TheOtherRoles // Lovers save next to be exiled, because RPC of ending game comes before RPC of exiled Lovers.notAckedExiledIsLover = false; - if (IHDMFDEEDEL != null) - Lovers.notAckedExiledIsLover = ((Lovers.lover1 != null && Lovers.lover1.PlayerId == IHDMFDEEDEL.PlayerId) || (Lovers.lover2 != null && Lovers.lover2.PlayerId == IHDMFDEEDEL.PlayerId)); + if (KLHCDCKJHKC != null) + Lovers.notAckedExiledIsLover = ((Lovers.lover1 != null && Lovers.lover1.PlayerId == KLHCDCKJHKC.GMBAIPNOKLP) || (Lovers.lover2 != null && Lovers.lover2.PlayerId == KLHCDCKJHKC.GMBAIPNOKLP)); } } static void onClick(int i, MeetingHud __instance) { - if (Swapper.swapper == null || PlayerControl.LocalPlayer != Swapper.swapper || Swapper.swapper.Data.IsDead) return; - if (__instance.state == MeetingHud.VoteStates.Results) return; - if (__instance.playerStates[i].isDead) return; + if (Swapper.swapper == null || PlayerControl.LocalPlayer != Swapper.swapper || Swapper.swapper.IDOFAMCIJKE.FGNJJFABIHJ) return; + if (__instance.MJMOOPLLNPO == MeetingHud.DDMMMDGMFIK.Results) return; + if (__instance.DHCOPOOJCLN[i].isDead) return; int selectedCount = selections.Where(b => b).Count(); SpriteRenderer renderer = renderers[i]; @@ -190,35 +246,35 @@ namespace TheOtherRoles for (int A = 0; A < selections.Length; A++) { if (selections[A]) { if (firstPlayer != null) { - secondPlayer = __instance.playerStates[A]; + secondPlayer = __instance.DHCOPOOJCLN[A]; break; } else { - firstPlayer = __instance.playerStates[A]; + firstPlayer = __instance.DHCOPOOJCLN[A]; } } } if (firstPlayer != null && secondPlayer != null) { MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.SwapperSwap, Hazel.SendOption.Reliable, -1); - writer.Write((byte)firstPlayer.TargetPlayerId); - writer.Write((byte)secondPlayer.TargetPlayerId); + writer.Write((byte)firstPlayer.HMPHKKGPLAG); + writer.Write((byte)secondPlayer.HMPHKKGPLAG); AmongUsClient.Instance.FinishRpcImmediately(writer); - RPCProcedure.swapperSwap((byte)firstPlayer.TargetPlayerId, (byte)secondPlayer.TargetPlayerId); + RPCProcedure.swapperSwap((byte)firstPlayer.HMPHKKGPLAG, (byte)secondPlayer.HMPHKKGPLAG); } } } } static void addSwapperSwapButtons(MeetingHud __instance) { - if (Swapper.swapper == null || PlayerControl.LocalPlayer != Swapper.swapper || Swapper.swapper.Data.IsDead) return; + if (Swapper.swapper == null || PlayerControl.LocalPlayer != Swapper.swapper || Swapper.swapper.IDOFAMCIJKE.FGNJJFABIHJ) return; - selections = new bool[__instance.playerStates.Length]; - renderers = new SpriteRenderer[__instance.playerStates.Length]; + selections = new bool[__instance.DHCOPOOJCLN.Length]; + renderers = new SpriteRenderer[__instance.DHCOPOOJCLN.Length]; - for (int i = 0; i < __instance.playerStates.Length; i++) + for (int i = 0; i < __instance.DHCOPOOJCLN.Length; i++) { - PlayerVoteArea playerVoteArea = __instance.playerStates[i]; + PlayerVoteArea playerVoteArea = __instance.DHCOPOOJCLN[i]; GameObject template = playerVoteArea.Buttons.transform.Find("CancelButton").gameObject; GameObject checkbox = UnityEngine.Object.Instantiate(template); checkbox.transform.SetParent(playerVoteArea.transform); @@ -251,10 +307,10 @@ namespace TheOtherRoles [HarmonyPatch(typeof(MeetingHud), nameof(MeetingHud.Deserialize))] class MeetingDeserializePatch { - static void Postfix(MeetingHud __instance, MessageReader HFPCBBHJIPJ, bool CHDIOBMNLGH) + static void Postfix(MeetingHud __instance, MessageReader DOOILGKLBBF, bool IHJEKEOFMGJ) { // Add swapper buttons - if (CHDIOBMNLGH) { + if (IHJEKEOFMGJ) { addSwapperSwapButtons(__instance); } } @@ -264,11 +320,28 @@ namespace TheOtherRoles [HarmonyPatch(typeof(ExileController), "Begin")] class ExileBeginPatch { - public static void Prefix(ref GameData.PlayerInfo IHDMFDEEDEL, bool DCHFIBODGIL) { - // Prevent growing Child exile - if (Child.child != null && IHDMFDEEDEL != null && IHDMFDEEDEL.PlayerId == Child.child.PlayerId && !Child.isGrownUp()) { - IHDMFDEEDEL = null; + public static void Prefix(ref GameData.OFKOJOKOOAK KLHCDCKJHKC, bool EMLKEPIBJLK) { + // Shifter shift + if (Shifter.shifter != null && AmongUsClient.Instance.CBKCIKKEJHI && Shifter.futureShift != null) { // We need to send the RPC from the host here, to make sure that the order of shifting and erasing is correct (for that reason the futureShifted and futureErased are being synced) + MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.ShifterShift, Hazel.SendOption.Reliable, -1); + writer.Write(Shifter.futureShift.PlayerId); + AmongUsClient.Instance.FinishRpcImmediately(writer); + RPCProcedure.shifterShift(Shifter.futureShift.PlayerId); + } + Shifter.futureShift = null; + + // Eraser erase + if (Eraser.eraser != null && AmongUsClient.Instance.CBKCIKKEJHI && Eraser.futureErased != null) { // We need to send the RPC from the host here, to make sure that the order of shifting and erasing is correct (for that reason the futureShifted and futureErased are being synced) + foreach (PlayerControl target in Eraser.futureErased) { + if (target != null) { + MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.ErasePlayerRole, Hazel.SendOption.Reliable, -1); + writer.Write(target.PlayerId); + AmongUsClient.Instance.FinishRpcImmediately(writer); + RPCProcedure.erasePlayerRole(target.PlayerId); + } + } } + Eraser.futureErased = new List(); } } @@ -282,17 +355,50 @@ namespace TheOtherRoles { // Reset custom button timers where necessary CustomButton.MeetingEndedUpdate(); + // Child set adapted cooldown + if (Child.child != null && PlayerControl.LocalPlayer == Child.child && Child.child.IDOFAMCIJKE.CIDDOFDJHJH) { + var multiplier = Child.isGrownUp() ? 0.66f : 2f; + Child.child.SetKillTimer(PlayerControl.GameOptions.ELBDIKIOHHH * multiplier); + } + + if (ExileController.Instance.KLHCDCKJHKC != null) { + byte exiledId = ExileController.Instance.KLHCDCKJHKC.GMBAIPNOKLP; - // Jester and Bounty Hunter win condition - if (ExileController.Instance.exiled != null) { - byte exiledId = ExileController.Instance.exiled.PlayerId; - if ((Jester.jester != null && Jester.jester.PlayerId == exiledId) || (BountyHunter.bountyHunter != null && !BountyHunter.bountyHunter.Data.IsDead && BountyHunter.target != null && BountyHunter.target.PlayerId == exiledId)) { + // Child lose condition + if (Child.child != null && Child.child.PlayerId == exiledId && !Child.isGrownUp() && !Child.child.IDOFAMCIJKE.CIDDOFDJHJH) { + MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.ChildLose, Hazel.SendOption.Reliable, -1); + AmongUsClient.Instance.FinishRpcImmediately(writer); + RPCProcedure.childLose(); + } + // Jester and Bounty Hunter win condition + else if ((Jester.jester != null && Jester.jester.PlayerId == exiledId) || (BountyHunter.bountyHunter != null && !BountyHunter.bountyHunter.IDOFAMCIJKE.FGNJJFABIHJ && BountyHunter.target != null && BountyHunter.target.PlayerId == exiledId)) { MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.JesterBountyHunterWin, Hazel.SendOption.Reliable, -1); writer.Write(exiledId); AmongUsClient.Instance.FinishRpcImmediately(writer); RPCProcedure.jesterBountyHunterWin(exiledId); } } + + // Seer spawn souls + if (Seer.deadBodyPositions != null && Seer.seer != null && PlayerControl.LocalPlayer == Seer.seer && (Seer.mode == 0 || Seer.mode == 2)) { + foreach (Vector3 pos in Seer.deadBodyPositions) { + GameObject soul = new GameObject(); + soul.transform.position = pos; + soul.layer = 5; + var rend = soul.AddComponent(); + rend.sprite = Seer.getSoulSprite(); + + PlayerControl.LocalPlayer.StartCoroutine(Effects.LDACHPMFOIF(Seer.soulDuration, new Action((p) => { + if (rend != null) { + var tmp = rend.color; + tmp.a = Mathf.Clamp01(1 - p); + rend.color = tmp; + } + if (p == 1f && rend?.gameObject != null) UnityEngine.Object.Destroy(rend.gameObject); + }))); + } + Seer.deadBodyPositions = new List(); + } } } } @@ -300,80 +406,82 @@ namespace TheOtherRoles [HarmonyPatch(typeof(TranslationController), nameof(TranslationController.GetString), new Type[] { typeof(StringNames), typeof(Il2CppReferenceArray) })] class MeetingExiledTextPatch { - static void Postfix(ref string __result, StringNames DKEHCKOHMOH, Il2CppReferenceArray DKBJCINDDCD) + static void Postfix(ref string __result, StringNames MKFNKGIBBHP, Il2CppReferenceArray BPBFAAEIABN) { - if (ExileController.Instance != null && ExileController.Instance.exiled != null) + if (ExileController.Instance != null && ExileController.Instance.KLHCDCKJHKC != null) { // Exile role text for roles that are being assigned to crewmates - if (DKEHCKOHMOH == StringNames.ExileTextPN || DKEHCKOHMOH == StringNames.ExileTextSN) + if (MKFNKGIBBHP == StringNames.ExileTextPN || MKFNKGIBBHP == StringNames.ExileTextSN) { - if( Jester.jester != null && ExileController.Instance.exiled.Object.PlayerId == Jester.jester.PlayerId) - __result = ExileController.Instance.exiled.PlayerName + " was The Jester."; - else if(Mayor.mayor != null && ExileController.Instance.exiled.Object.PlayerId == Mayor.mayor.PlayerId) - __result = ExileController.Instance.exiled.PlayerName + " was The Mayor."; - else if(Engineer.engineer != null && ExileController.Instance.exiled.Object.PlayerId == Engineer.engineer.PlayerId) - __result = ExileController.Instance.exiled.PlayerName + " was The Engineer."; - else if(Sheriff.sheriff != null && ExileController.Instance.exiled.Object.PlayerId == Sheriff.sheriff.PlayerId) - __result = ExileController.Instance.exiled.PlayerName + " was The Sheriff."; - else if(Lighter.lighter != null && ExileController.Instance.exiled.Object.PlayerId == Lighter.lighter.PlayerId) - __result = ExileController.Instance.exiled.PlayerName + " was The Lighter."; - else if(Detective.detective != null && ExileController.Instance.exiled.Object.PlayerId == Detective.detective.PlayerId) - __result = ExileController.Instance.exiled.PlayerName + " was The Detective."; - else if(TimeMaster.timeMaster != null && ExileController.Instance.exiled.Object.PlayerId == TimeMaster.timeMaster.PlayerId) - __result = ExileController.Instance.exiled.PlayerName + " was The Time Master."; - else if(Medic.medic != null && ExileController.Instance.exiled.Object.PlayerId == Medic.medic.PlayerId) - __result = ExileController.Instance.exiled.PlayerName + " was The Medic."; - else if(Shifter.shifter != null && ExileController.Instance.exiled.Object.PlayerId == Shifter.shifter.PlayerId) - __result = ExileController.Instance.exiled.PlayerName + " was The Shifter."; - else if(Swapper.swapper != null && ExileController.Instance.exiled.Object.PlayerId == Swapper.swapper.PlayerId) - __result = ExileController.Instance.exiled.PlayerName + " was The Swapper."; - else if(Lovers.lover1 != null && ExileController.Instance.exiled.Object.PlayerId == Lovers.lover1.PlayerId) - __result = ExileController.Instance.exiled.PlayerName + " was The Lover."; - else if(Lovers.lover2 != null && ExileController.Instance.exiled.Object.PlayerId == Lovers.lover2.PlayerId) - __result = ExileController.Instance.exiled.PlayerName + " was The Lover."; - else if(Seer.seer != null && ExileController.Instance.exiled.Object.PlayerId == Seer.seer.PlayerId) - __result = ExileController.Instance.exiled.PlayerName + " was The Seer."; - else if(Spy.spy != null && ExileController.Instance.exiled.Object.PlayerId == Spy.spy.PlayerId) - __result = ExileController.Instance.exiled.PlayerName + " was The Spy."; - else if(Child.child != null && ExileController.Instance.exiled.Object.PlayerId == Child.child.PlayerId) - __result = ExileController.Instance.exiled.PlayerName + " was The Child."; - else if(BountyHunter.bountyHunter != null && ExileController.Instance.exiled.Object.PlayerId == BountyHunter.bountyHunter.PlayerId) - __result = ExileController.Instance.exiled.PlayerName + " was The Bounty Hunter."; - else if(Tracker.tracker != null && ExileController.Instance.exiled.Object.PlayerId == Tracker.tracker.PlayerId) - __result = ExileController.Instance.exiled.PlayerName + " was The Tracker."; - else if(Snitch.snitch != null && ExileController.Instance.exiled.Object.PlayerId == Snitch.snitch.PlayerId) - __result = ExileController.Instance.exiled.PlayerName + " was The Snitch."; - else if(Jackal.jackal != null && ExileController.Instance.exiled.Object.PlayerId == Jackal.jackal.PlayerId) - __result = ExileController.Instance.exiled.PlayerName + " was The Jackal."; - else if(Sidekick.sidekick != null && ExileController.Instance.exiled.Object.PlayerId == Sidekick.sidekick.PlayerId) - __result = ExileController.Instance.exiled.PlayerName + " was The Sidekick."; + if( Jester.jester != null && ExileController.Instance.KLHCDCKJHKC.GPBBCHGPABL.PlayerId == Jester.jester.PlayerId) + __result = ExileController.Instance.KLHCDCKJHKC.HGGCLJHCDBM + " was The Jester."; + else if(Mayor.mayor != null && ExileController.Instance.KLHCDCKJHKC.GPBBCHGPABL.PlayerId == Mayor.mayor.PlayerId) + __result = ExileController.Instance.KLHCDCKJHKC.HGGCLJHCDBM + " was The Mayor."; + else if(Engineer.engineer != null && ExileController.Instance.KLHCDCKJHKC.GPBBCHGPABL.PlayerId == Engineer.engineer.PlayerId) + __result = ExileController.Instance.KLHCDCKJHKC.HGGCLJHCDBM + " was The Engineer."; + else if(Sheriff.sheriff != null && ExileController.Instance.KLHCDCKJHKC.GPBBCHGPABL.PlayerId == Sheriff.sheriff.PlayerId) + __result = ExileController.Instance.KLHCDCKJHKC.HGGCLJHCDBM + " was The Sheriff."; + else if(Lighter.lighter != null && ExileController.Instance.KLHCDCKJHKC.GPBBCHGPABL.PlayerId == Lighter.lighter.PlayerId) + __result = ExileController.Instance.KLHCDCKJHKC.HGGCLJHCDBM + " was The Lighter."; + else if(Detective.detective != null && ExileController.Instance.KLHCDCKJHKC.GPBBCHGPABL.PlayerId == Detective.detective.PlayerId) + __result = ExileController.Instance.KLHCDCKJHKC.HGGCLJHCDBM + " was The Detective."; + else if(TimeMaster.timeMaster != null && ExileController.Instance.KLHCDCKJHKC.GPBBCHGPABL.PlayerId == TimeMaster.timeMaster.PlayerId) + __result = ExileController.Instance.KLHCDCKJHKC.HGGCLJHCDBM + " was The Time Master."; + else if(Medic.medic != null && ExileController.Instance.KLHCDCKJHKC.GPBBCHGPABL.PlayerId == Medic.medic.PlayerId) + __result = ExileController.Instance.KLHCDCKJHKC.HGGCLJHCDBM + " was The Medic."; + else if(Shifter.shifter != null && ExileController.Instance.KLHCDCKJHKC.GPBBCHGPABL.PlayerId == Shifter.shifter.PlayerId) + __result = ExileController.Instance.KLHCDCKJHKC.HGGCLJHCDBM + " was The Shifter."; + else if(Swapper.swapper != null && ExileController.Instance.KLHCDCKJHKC.GPBBCHGPABL.PlayerId == Swapper.swapper.PlayerId) + __result = ExileController.Instance.KLHCDCKJHKC.HGGCLJHCDBM + " was The Swapper."; + else if(Lovers.lover1 != null && ExileController.Instance.KLHCDCKJHKC.GPBBCHGPABL.PlayerId == Lovers.lover1.PlayerId) + __result = ExileController.Instance.KLHCDCKJHKC.HGGCLJHCDBM + " was The Lover."; + else if(Lovers.lover2 != null && ExileController.Instance.KLHCDCKJHKC.GPBBCHGPABL.PlayerId == Lovers.lover2.PlayerId) + __result = ExileController.Instance.KLHCDCKJHKC.HGGCLJHCDBM + " was The Lover."; + else if(Seer.seer != null && ExileController.Instance.KLHCDCKJHKC.GPBBCHGPABL.PlayerId == Seer.seer.PlayerId) + __result = ExileController.Instance.KLHCDCKJHKC.HGGCLJHCDBM + " was The Seer."; + else if(Hacker.hacker != null && ExileController.Instance.KLHCDCKJHKC.GPBBCHGPABL.PlayerId == Hacker.hacker.PlayerId) + __result = ExileController.Instance.KLHCDCKJHKC.HGGCLJHCDBM + " was The Hacker."; + else if(Child.child != null && ExileController.Instance.KLHCDCKJHKC.GPBBCHGPABL.PlayerId == Child.child.PlayerId) + __result = ExileController.Instance.KLHCDCKJHKC.HGGCLJHCDBM + " was The Child."; + else if(BountyHunter.bountyHunter != null && ExileController.Instance.KLHCDCKJHKC.GPBBCHGPABL.PlayerId == BountyHunter.bountyHunter.PlayerId) + __result = ExileController.Instance.KLHCDCKJHKC.HGGCLJHCDBM + " was The Bounty Hunter."; + else if(Tracker.tracker != null && ExileController.Instance.KLHCDCKJHKC.GPBBCHGPABL.PlayerId == Tracker.tracker.PlayerId) + __result = ExileController.Instance.KLHCDCKJHKC.HGGCLJHCDBM + " was The Tracker."; + else if(Snitch.snitch != null && ExileController.Instance.KLHCDCKJHKC.GPBBCHGPABL.PlayerId == Snitch.snitch.PlayerId) + __result = ExileController.Instance.KLHCDCKJHKC.HGGCLJHCDBM + " was The Snitch."; + else if(Jackal.jackal != null && ExileController.Instance.KLHCDCKJHKC.GPBBCHGPABL.PlayerId == Jackal.jackal.PlayerId) + __result = ExileController.Instance.KLHCDCKJHKC.HGGCLJHCDBM + " was The Jackal."; + else if(Sidekick.sidekick != null && ExileController.Instance.KLHCDCKJHKC.GPBBCHGPABL.PlayerId == Sidekick.sidekick.PlayerId) + __result = ExileController.Instance.KLHCDCKJHKC.HGGCLJHCDBM + " was The Sidekick."; else - __result = ExileController.Instance.exiled.PlayerName + " was not The Impostor."; + __result = ExileController.Instance.KLHCDCKJHKC.HGGCLJHCDBM + " was not The Impostor."; } // Exile role text for roles that are being assigned to impostors - if (DKEHCKOHMOH == StringNames.ExileTextPP || DKEHCKOHMOH == StringNames.ExileTextSP) { - if(Godfather.godfather != null && ExileController.Instance.exiled.Object.PlayerId == Godfather.godfather.PlayerId) - __result = ExileController.Instance.exiled.PlayerName + " was The Godfather."; - else if(Mafioso.mafioso != null && ExileController.Instance.exiled.Object.PlayerId == Mafioso.mafioso.PlayerId) - __result = ExileController.Instance.exiled.PlayerName + " was The Mafioso."; - else if(Janitor.janitor != null && ExileController.Instance.exiled.Object.PlayerId == Janitor.janitor.PlayerId) - __result = ExileController.Instance.exiled.PlayerName + " was The Janitor."; - else if(Morphling.morphling != null && ExileController.Instance.exiled.Object.PlayerId == Morphling.morphling.PlayerId) - __result = ExileController.Instance.exiled.PlayerName + " was The Morphling."; - else if(Camouflager.camouflager != null && ExileController.Instance.exiled.Object.PlayerId == Camouflager.camouflager.PlayerId) - __result = ExileController.Instance.exiled.PlayerName + " was The Camouflager."; - else if(Lovers.lover1 != null && ExileController.Instance.exiled.Object.PlayerId == Lovers.lover1.PlayerId) - __result = ExileController.Instance.exiled.PlayerName + " was The ImpLover."; - else if(Lovers.lover2 != null && ExileController.Instance.exiled.Object.PlayerId == Lovers.lover2.PlayerId) - __result = ExileController.Instance.exiled.PlayerName + " was The ImpLover."; - else if(Vampire.vampire != null && ExileController.Instance.exiled.Object.PlayerId == Vampire.vampire.PlayerId) - __result = ExileController.Instance.exiled.PlayerName + " was The Vampire."; + if (MKFNKGIBBHP == StringNames.ExileTextPP || MKFNKGIBBHP == StringNames.ExileTextSP) { + if(Godfather.godfather != null && ExileController.Instance.KLHCDCKJHKC.GPBBCHGPABL.PlayerId == Godfather.godfather.PlayerId) + __result = ExileController.Instance.KLHCDCKJHKC.HGGCLJHCDBM + " was The Godfather."; + else if(Mafioso.mafioso != null && ExileController.Instance.KLHCDCKJHKC.GPBBCHGPABL.PlayerId == Mafioso.mafioso.PlayerId) + __result = ExileController.Instance.KLHCDCKJHKC.HGGCLJHCDBM + " was The Mafioso."; + else if(Janitor.janitor != null && ExileController.Instance.KLHCDCKJHKC.GPBBCHGPABL.PlayerId == Janitor.janitor.PlayerId) + __result = ExileController.Instance.KLHCDCKJHKC.HGGCLJHCDBM + " was The Janitor."; + else if(Morphling.morphling != null && ExileController.Instance.KLHCDCKJHKC.GPBBCHGPABL.PlayerId == Morphling.morphling.PlayerId) + __result = ExileController.Instance.KLHCDCKJHKC.HGGCLJHCDBM + " was The Morphling."; + else if(Camouflager.camouflager != null && ExileController.Instance.KLHCDCKJHKC.GPBBCHGPABL.PlayerId == Camouflager.camouflager.PlayerId) + __result = ExileController.Instance.KLHCDCKJHKC.HGGCLJHCDBM + " was The Camouflager."; + else if(Lovers.lover1 != null && ExileController.Instance.KLHCDCKJHKC.GPBBCHGPABL.PlayerId == Lovers.lover1.PlayerId) + __result = ExileController.Instance.KLHCDCKJHKC.HGGCLJHCDBM + " was The ImpLover."; + else if(Lovers.lover2 != null && ExileController.Instance.KLHCDCKJHKC.GPBBCHGPABL.PlayerId == Lovers.lover2.PlayerId) + __result = ExileController.Instance.KLHCDCKJHKC.HGGCLJHCDBM + " was The ImpLover."; + else if(Vampire.vampire != null && ExileController.Instance.KLHCDCKJHKC.GPBBCHGPABL.PlayerId == Vampire.vampire.PlayerId) + __result = ExileController.Instance.KLHCDCKJHKC.HGGCLJHCDBM + " was The Vampire."; + else if (Eraser.eraser != null && ExileController.Instance.KLHCDCKJHKC.GPBBCHGPABL.PlayerId == Eraser.eraser.PlayerId) + __result = ExileController.Instance.KLHCDCKJHKC.HGGCLJHCDBM + " was The Eraser."; } // Hide number of remaining impostors on Jester win - if (DKEHCKOHMOH == StringNames.ImpostorsRemainP || DKEHCKOHMOH == StringNames.ImpostorsRemainS) + if (MKFNKGIBBHP == StringNames.ImpostorsRemainP || MKFNKGIBBHP == StringNames.ImpostorsRemainS) { - if (Jester.jester != null && ExileController.Instance.exiled.Object.PlayerId == Jester.jester.PlayerId) + if (Jester.jester != null && ExileController.Instance.KLHCDCKJHKC.GPBBCHGPABL.PlayerId == Jester.jester.PlayerId) __result = ""; } } diff --git a/Source Code/PlayerControlPatch.cs b/Source Code/PlayerControlPatch.cs index ea8ad8d..c1cc418 100644 --- a/Source Code/PlayerControlPatch.cs +++ b/Source Code/PlayerControlPatch.cs @@ -7,8 +7,17 @@ using System.Text; using System.Threading.Tasks; using static TheOtherRoles.TheOtherRoles; using static TheOtherRoles.GameHistory; +using static TheOtherRoles.MapOptions; using UnityEngine; +using SystemTypes = LGBKLKNAINN; +using Palette = GLNPIJPGGNJ; +using Constants = NFONDPLFBCP; +using PhysicsHelpers = IEPBCHBGDOA; +using DeathReason = KAPJFCMEBJE; +using GameOptionsData = IGDMNKLDEPI; +using Effects = HLPCBNMDEHF; + namespace TheOtherRoles { [HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.FixedUpdate))] public static class PlayerControlFixedUpdatePatch @@ -22,21 +31,9 @@ namespace TheOtherRoles { PlayerControl.LocalPlayer.transform.position = next.Item1; localPlayerPositions.RemoveAt(0); if (localPlayerPositions.Count > 0) localPlayerPositions.RemoveAt(0); // Skip every second position to rewinde in half the time - - // Try reviving LOCAL player - if (TimeMaster.reviveDuringRewind && PlayerControl.LocalPlayer.Data.IsDead) { - DeadPlayer deadPlayer = deadPlayers.Where(x => x.player == PlayerControl.LocalPlayer).FirstOrDefault(); - if (deadPlayer != null && next.Item2 < deadPlayer.timeOfDeath) { - MessageWriter write = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte) CustomRPC.TimeMasterRevive, Hazel.SendOption.Reliable, -1); - write.Write(PlayerControl.LocalPlayer.PlayerId); - AmongUsClient.Instance.FinishRpcImmediately(write); - RPCProcedure.timeMasterRevive(PlayerControl.LocalPlayer.PlayerId); - } - } } else { TimeMaster.isRewinding = false; PlayerControl.LocalPlayer.moveable = true; - HudManager.Instance.FullScreen.enabled = false; } } else { while (localPlayerPositions.Count >= Mathf.Round(TimeMaster.rewindTime / Time.fixedDeltaTime)) localPlayerPositions.RemoveAt(localPlayerPositions.Count - 1); @@ -46,17 +43,17 @@ namespace TheOtherRoles { static PlayerControl setTarget(bool onlyCrewmates = false, bool targetPlayersInVents = false, List untargetablePlayers = null) { PlayerControl result = null; - float num = GameOptionsData.KillDistances[Mathf.Clamp(PlayerControl.GameOptions.KillDistance, 0, 2)]; + float num = GameOptionsData.FECFGOOCIJL[Mathf.Clamp(PlayerControl.GameOptions.MLLMFMOMIAC, 0, 2)]; if (!ShipStatus.Instance) return result; Vector2 truePosition = PlayerControl.LocalPlayer.GetTruePosition(); - Il2CppSystem.Collections.Generic.List allPlayers = GameData.Instance.AllPlayers; + Il2CppSystem.Collections.Generic.List allPlayers = GameData.Instance.AllPlayers; for (int i = 0; i < allPlayers.Count; i++) { - GameData.PlayerInfo playerInfo = allPlayers[i]; - if (!playerInfo.Disconnected && playerInfo.PlayerId != PlayerControl.LocalPlayer.PlayerId && !playerInfo.IsDead && (!onlyCrewmates || !playerInfo.IsImpostor)) + GameData.OFKOJOKOOAK OFKOJOKOOAK = allPlayers[i]; + if (!OFKOJOKOOAK.GBPMEHJFECK && OFKOJOKOOAK.GMBAIPNOKLP != PlayerControl.LocalPlayer.PlayerId && !OFKOJOKOOAK.FGNJJFABIHJ && (!onlyCrewmates || !OFKOJOKOOAK.CIDDOFDJHJH)) { - PlayerControl @object = playerInfo.Object; + PlayerControl @object = OFKOJOKOOAK.GPBBCHGPABL; if(untargetablePlayers != null && untargetablePlayers.Any(x => x == @object)) { // if that player is not targetable: skip check continue; @@ -66,7 +63,7 @@ namespace TheOtherRoles { { Vector2 vector = @object.GetTruePosition() - truePosition; float magnitude = vector.magnitude; - if (magnitude <= num && !PhysicsHelpers.AnyNonTriggersBetween(truePosition, vector.normalized, magnitude, Constants.ShipAndObjectsMask)) + if (magnitude <= num && !PhysicsHelpers.HKFKKEKGLHF(truePosition, vector.normalized, magnitude, Constants.DHLPLBPJNBA)) { result = @object; num = magnitude; @@ -98,25 +95,19 @@ namespace TheOtherRoles { Sheriff.currentTarget = setTarget(); } - static void seerSetTarget() { - if (Seer.seer == null || Seer.seer != PlayerControl.LocalPlayer) return; - Seer.currentTarget = setTarget(); - if (Seer.currentTarget != null && Seer.revealedPlayers.Keys.Any(p => p.Data.PlayerId == Seer.currentTarget.Data.PlayerId)) Seer.currentTarget = null; // Remove target if already revealed - } - static void trackerSetTarget() { if (Tracker.tracker == null || Tracker.tracker != PlayerControl.LocalPlayer) return; Tracker.currentTarget = setTarget(); } - static void detectiveSetFootPrints() { + static void detectiveUpdateFootPrints() { if (Detective.detective == null || Detective.detective != PlayerControl.LocalPlayer) return; Detective.timer -= Time.fixedDeltaTime; if (Detective.timer <= 0f) { Detective.timer = Detective.footprintIntervall; foreach (PlayerControl player in PlayerControl.AllPlayerControls) { - if (player != null && player != PlayerControl.LocalPlayer && !player.Data.IsDead && !player.inVent) { + if (player != null && player != PlayerControl.LocalPlayer && !player.IDOFAMCIJKE.FGNJJFABIHJ && !player.inVent) { new Footprint(Detective.footprintDuration, Detective.anonymousFootprints, player); } } @@ -157,17 +148,24 @@ namespace TheOtherRoles { Sidekick.currentTarget = setTarget(untargetablePlayers : untargetablePlayers); } + static void eraserSetTarget() { + if (Eraser.eraser == null || Eraser.eraser != PlayerControl.LocalPlayer) return; + Eraser.currentTarget = setTarget(true); + } + static void engineerUpdate() { - if (PlayerControl.LocalPlayer.Data.IsImpostor) { - foreach (Vent vent in ShipStatus.Instance.AllVents) { - if (vent.Field_7?.material != null) { - if (Engineer.engineer != null && Engineer.engineer.inVent) { - vent.Field_7.material.SetFloat("_Outline", 1f); - vent.Field_7.material.SetColor("_OutlineColor", Engineer.color); - } else if (vent.Field_7.material.GetColor("_AddColor") != Color.red) { - vent.Field_7.material.SetFloat("_Outline", 0); + if (PlayerControl.LocalPlayer.IDOFAMCIJKE.CIDDOFDJHJH && ShipStatus.Instance?.GIDPCPOEFBC != null) { + foreach (Vent vent in ShipStatus.Instance.GIDPCPOEFBC) { + try { + if (vent?.LNMJKMLHMIM?.material != null) { + if (Engineer.engineer != null && Engineer.engineer.inVent) { + vent.LNMJKMLHMIM.material.SetFloat("_Outline", 1f); + vent.LNMJKMLHMIM.material.SetColor("_OutlineColor", Engineer.color); + } else if (vent.LNMJKMLHMIM.material.GetColor("_AddColor") != Color.red) { + vent.LNMJKMLHMIM.material.SetFloat("_Outline", 0); + } } - } + } catch {} } } } @@ -180,11 +178,11 @@ namespace TheOtherRoles { return; } - if (Tracker.tracker != null && Tracker.tracked != null && PlayerControl.LocalPlayer == Tracker.tracker && !Tracker.tracker.Data.IsDead) { + if (Tracker.tracker != null && Tracker.tracked != null && PlayerControl.LocalPlayer == Tracker.tracker && !Tracker.tracker.IDOFAMCIJKE.FGNJJFABIHJ) { Tracker.timeUntilUpdate -= Time.fixedDeltaTime; if (Tracker.timeUntilUpdate <= 0f) { - bool trackedOnMap = !Tracker.tracked.Data.IsDead; + bool trackedOnMap = !Tracker.tracked.IDOFAMCIJKE.FGNJJFABIHJ; Vector3 position = Tracker.tracked.transform.position; if (!trackedOnMap) { // Check for dead body DeadBody body = UnityEngine.Object.FindObjectsOfType().FirstOrDefault(b => b.ParentId == Tracker.tracked.PlayerId); @@ -204,7 +202,10 @@ namespace TheOtherRoles { } public static void Postfix(PlayerControl __instance) { - if (AmongUsClient.Instance.GameState != InnerNet.InnerNetClient.GameStates.Started) return; + if (AmongUsClient.Instance.GameState != InnerNet.InnerNetClient.CJDCOJJNIGL.Started) return; + + // Update Role Description + Helpers.refreshRoleDescription(__instance); if (PlayerControl.LocalPlayer == __instance) { // Time Master @@ -217,15 +218,15 @@ namespace TheOtherRoles { shifterSetTarget(); // Sheriff sheriffSetTarget(); - // Seer - seerSetTarget(); // Detective - detectiveSetFootPrints(); + detectiveUpdateFootPrints(); // Tracker trackerSetTarget(); // Vampire vampireSetTarget(); Garlic.UpdateAll(); + // Eraser + eraserSetTarget(); // Engineer engineerUpdate(); // Tracker @@ -238,21 +239,31 @@ namespace TheOtherRoles { } } - [HarmonyPatch(typeof(HudManager), nameof(HudManager.OpenMeetingRoom))] - class StartMeetingHostPatch { + [HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.CmdReportDeadBody))] + class StartMeetingPatcher { public static void Prefix(PlayerControl __instance) { - // Perform vampire bite kill before the meeting starts for HOST - if (!MeetingHud.Instance && AmongUsClient.Instance.AmHost) + // Murder the bitten player before the meeting starts or reset the bitten player + if (Vampire.bitten != null && !Vampire.bitten.IDOFAMCIJKE.FGNJJFABIHJ && Helpers.handleMurderAttempt(Vampire.bitten, true)) { + MessageWriter killWriter = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.VampireTryKill, Hazel.SendOption.Reliable, -1); + AmongUsClient.Instance.FinishRpcImmediately(killWriter); RPCProcedure.vampireTryKill(); + } else { + MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.VampireSetBitten, Hazel.SendOption.Reliable, -1); + writer.Write(byte.MaxValue); + writer.Write(byte.MaxValue); + AmongUsClient.Instance.FinishRpcImmediately(writer); + RPCProcedure.vampireSetBitten(byte.MaxValue, byte.MaxValue); + } } } [HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.CoStartMeeting))] - class StartMeetingClientPatch { - public static void Prefix(PlayerControl __instance) { - // Perform vampire bite kill before the meeting starts for CLIENTS - if (AmongUsClient.Instance.AmClient) - RPCProcedure.vampireTryKill(); + class StartMeetingPatch { + public static void Prefix(PlayerControl __instance, GameData.OFKOJOKOOAK IGLDJOKKFJE) { + // Reset vampire bitten + Vampire.bitten = null; + // Count meetings + if (IGLDJOKKFJE == null) meetingsCount++; } } @@ -267,49 +278,41 @@ namespace TheOtherRoles { [HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.LocalPlayer.CmdReportDeadBody))] class BodyReportPatch { - static void Postfix(PlayerControl __instance, GameData.PlayerInfo PAIBDFDMIGK) + static void Postfix(PlayerControl __instance, GameData.OFKOJOKOOAK IGLDJOKKFJE) { - // Medic report - if (Medic.medic != null && Medic.medic == PlayerControl.LocalPlayer && __instance.PlayerId == Medic.medic.PlayerId) + // Medic or Detective report + bool isMedicReport = Medic.medic != null && Medic.medic == PlayerControl.LocalPlayer && __instance.PlayerId == Medic.medic.PlayerId; + bool isDetectiveReport = Detective.detective != null && Detective.detective == PlayerControl.LocalPlayer && __instance.PlayerId == Detective.detective.PlayerId; + if (isMedicReport || isDetectiveReport) { - DeadPlayer deadPlayer = deadPlayers?.Where(x => x.player?.PlayerId == PAIBDFDMIGK?.PlayerId)?.FirstOrDefault(); + DeadPlayer deadPlayer = deadPlayers?.Where(x => x.player?.PlayerId == IGLDJOKKFJE?.GMBAIPNOKLP)?.FirstOrDefault(); if (deadPlayer != null && deadPlayer.killerIfExisting != null) { float timeSinceDeath = ((float)(DateTime.UtcNow - deadPlayer.timeOfDeath).TotalMilliseconds); string msg = ""; - if (timeSinceDeath < Medic.reportNameDuration * 1000) { - msg = $"Body Report: The killer appears to be {deadPlayer.killerIfExisting.name}! (Killed {Math.Round(timeSinceDeath / 1000)}s ago)"; - } else if (timeSinceDeath < Medic.reportColorDuration * 1000) { - var colors = new Dictionary() { - {0, "darker"}, - {1, "darker"}, - {2, "darker"}, - {3, "lighter"}, - {4, "lighter"}, - {5, "lighter"}, - {6, "darker"}, - {7, "lighter"}, - {8, "darker"}, - {9, "darker"}, - {10, "lighter"}, - {11, "lighter"}, - }; - var typeOfColor = colors[deadPlayer.killerIfExisting.Data.ColorId] ?? "unknown"; - msg = $"Body Report: The killer appears to be a {typeOfColor} color. (Killed {Math.Round(timeSinceDeath / 1000)}s ago)"; - } else { - msg = $"Body Report: The corpse is too old to gain information from. (Killed {Math.Round(timeSinceDeath / 1000)}s ago)"; + if (isMedicReport) { + msg = $"Body Report: Killed {Math.Round(timeSinceDeath / 1000)}s ago!"; + } else if (isDetectiveReport) { + if (timeSinceDeath < Detective.reportNameDuration * 1000) { + msg = $"Body Report: The killer appears to be {deadPlayer.killerIfExisting.name}!"; + } else if (timeSinceDeath < Detective.reportColorDuration * 1000) { + var typeOfColor = Helpers.isLighterColor(deadPlayer.killerIfExisting.IDOFAMCIJKE.JFHFMIKFHGG) ? "darker" : "lighter"; + msg = $"Body Report: The killer appears to be a {typeOfColor} color!"; + } else { + msg = $"Body Report: The corpse is too old to gain information from!"; + } } if (!string.IsNullOrWhiteSpace(msg)) { - if (AmongUsClient.Instance.AmClient && DestroyableSingleton.Instance) + if (AmongUsClient.Instance.HNMILJEOEKN && DestroyableSingleton.CMJOLNCMAPD) { - DestroyableSingleton.Instance.Chat.AddChat(PlayerControl.LocalPlayer, msg); + DestroyableSingleton.CMJOLNCMAPD.Chat.AddChat(PlayerControl.LocalPlayer, msg); } if (msg.IndexOf("who", StringComparison.OrdinalIgnoreCase) >= 0) { - DestroyableSingleton.Instance.SendWho(); + DestroyableSingleton.CMJOLNCMAPD.SendWho(); } } } @@ -323,29 +326,29 @@ namespace TheOtherRoles { public static bool resetToCrewmate = false; public static bool resetToDead = false; - public static void Prefix(PlayerControl __instance, PlayerControl PAIBDFDMIGK) + public static void Prefix(PlayerControl __instance, PlayerControl IGLDJOKKFJE) { // Allow everyone to murder players - resetToCrewmate = !__instance.Data.IsImpostor; - resetToDead = __instance.Data.IsDead; - __instance.Data.IsImpostor = true; - __instance.Data.IsDead = false; + resetToCrewmate = !__instance.IDOFAMCIJKE.CIDDOFDJHJH; + resetToDead = __instance.IDOFAMCIJKE.FGNJJFABIHJ; + __instance.IDOFAMCIJKE.CIDDOFDJHJH = true; + __instance.IDOFAMCIJKE.FGNJJFABIHJ = false; } - public static void Postfix(PlayerControl __instance, PlayerControl PAIBDFDMIGK) + public static void Postfix(PlayerControl __instance, PlayerControl IGLDJOKKFJE) { // Collect dead player info - DeadPlayer deadPlayer = new DeadPlayer(PAIBDFDMIGK, DateTime.UtcNow, DeathReason.Kill, __instance); + DeadPlayer deadPlayer = new DeadPlayer(IGLDJOKKFJE, DateTime.UtcNow, DeathReason.Kill, __instance); GameHistory.deadPlayers.Add(deadPlayer); // Reset killer to crewmate if resetToCrewmate - if (resetToCrewmate) __instance.Data.IsImpostor = false; - if (resetToDead) __instance.Data.IsDead = true; + if (resetToCrewmate) __instance.IDOFAMCIJKE.CIDDOFDJHJH = false; + if (resetToDead) __instance.IDOFAMCIJKE.FGNJJFABIHJ = true; // Lover suicide trigger on murder - if ((Lovers.lover1 != null && PAIBDFDMIGK == Lovers.lover1) || (Lovers.lover2 != null && PAIBDFDMIGK == Lovers.lover2)) { - PlayerControl otherLover = PAIBDFDMIGK == Lovers.lover1 ? Lovers.lover2 : Lovers.lover1; - if (PlayerControl.LocalPlayer == PAIBDFDMIGK && otherLover != null && !otherLover.Data.IsDead && Lovers.bothDie) { // Only the dead lover sends the rpc + if ((Lovers.lover1 != null && IGLDJOKKFJE == Lovers.lover1) || (Lovers.lover2 != null && IGLDJOKKFJE == Lovers.lover2)) { + PlayerControl otherLover = IGLDJOKKFJE == Lovers.lover1 ? Lovers.lover2 : Lovers.lover1; + if (PlayerControl.LocalPlayer == IGLDJOKKFJE && otherLover != null && !otherLover.IDOFAMCIJKE.FGNJJFABIHJ && Lovers.bothDie) { // Only the dead lover sends the rpc MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.LoverSuicide, Hazel.SendOption.Reliable, -1); writer.Write(otherLover.PlayerId); AmongUsClient.Instance.FinishRpcImmediately(writer); @@ -354,19 +357,42 @@ namespace TheOtherRoles { } // Sidekick promotion trigger on murder - if (Sidekick.promotesToJackal && Sidekick.sidekick != null && !Sidekick.sidekick.Data.IsDead && PAIBDFDMIGK == Jackal.jackal) { + if (Sidekick.promotesToJackal && Sidekick.sidekick != null && !Sidekick.sidekick.IDOFAMCIJKE.FGNJJFABIHJ && IGLDJOKKFJE == Jackal.jackal && Jackal.jackal == PlayerControl.LocalPlayer) { MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.SidekickPromotes, Hazel.SendOption.Reliable, -1); AmongUsClient.Instance.FinishRpcImmediately(writer); RPCProcedure.sidekickPromotes(); } + + // Seer show flash and add dead player position + if (Seer.seer != null && PlayerControl.LocalPlayer == Seer.seer && !Seer.seer.IDOFAMCIJKE.FGNJJFABIHJ && Seer.seer != IGLDJOKKFJE && Seer.mode <= 1) { + HudManager.CMJOLNCMAPD.FullScreen.enabled = true; + HudManager.CMJOLNCMAPD.StartCoroutine(Effects.LDACHPMFOIF(1f, new Action((p) => { + var renderer = HudManager.CMJOLNCMAPD.FullScreen; + if (p < 0.5) { + if (renderer != null) + renderer.color = new Color(42f / 255f, 187f / 255f, 245f / 255f, Mathf.Clamp01(p * 2 * 0.75f)); + } else { + if (renderer != null) + renderer.color = new Color(42f / 255f, 187f / 255f, 245f / 255f, Mathf.Clamp01((1-p) * 2 * 0.75f)); + } + if (p == 1f && renderer != null) renderer.enabled = false; + }))); + } + if (Seer.deadBodyPositions != null) Seer.deadBodyPositions.Add(IGLDJOKKFJE.transform.position); + + // Child set adapted kill cooldown + if (Child.child != null && PlayerControl.LocalPlayer == Child.child && Child.child.IDOFAMCIJKE.CIDDOFDJHJH) { + var multiplier = Child.isGrownUp() ? 0.66f : 2f; + Child.child.SetKillTimer(PlayerControl.GameOptions.ELBDIKIOHHH * multiplier); + } } } [HarmonyPatch(typeof(KillAnimation),nameof(KillAnimation.CoPerformKill))] class Test { - public static void Prefix(KillAnimation __instance, ref PlayerControl CPKODPCJPOO, ref PlayerControl PAIBDFDMIGK) { - if (Vampire.vampire != null && Vampire.vampire == CPKODPCJPOO && Vampire.bitten != null && Vampire.bitten == PAIBDFDMIGK) - CPKODPCJPOO = PAIBDFDMIGK; + public static void Prefix(KillAnimation __instance, ref PlayerControl KMMMAPHIMLH, ref PlayerControl IGLDJOKKFJE) { + if (Vampire.vampire != null && Vampire.vampire == KMMMAPHIMLH && Vampire.bitten != null && Vampire.bitten == IGLDJOKKFJE) + KMMMAPHIMLH = IGLDJOKKFJE; } } @@ -382,49 +408,16 @@ namespace TheOtherRoles { // Lover suicide trigger on exile if ((Lovers.lover1 != null && __instance == Lovers.lover1) || (Lovers.lover2 != null && __instance == Lovers.lover2)) { PlayerControl otherLover = __instance == Lovers.lover1 ? Lovers.lover2 : Lovers.lover1; - if (otherLover != null && !otherLover.Data.IsDead && Lovers.bothDie) + if (otherLover != null && !otherLover.IDOFAMCIJKE.FGNJJFABIHJ && Lovers.bothDie) otherLover.Exiled(); } // Sidekick promotion trigger on exile - if (Sidekick.promotesToJackal && Sidekick.sidekick != null && !Sidekick.sidekick.Data.IsDead && __instance == Jackal.jackal) { + if (Sidekick.promotesToJackal && Sidekick.sidekick != null && !Sidekick.sidekick.IDOFAMCIJKE.FGNJJFABIHJ && __instance == Jackal.jackal && Jackal.jackal == PlayerControl.LocalPlayer) { MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.SidekickPromotes, Hazel.SendOption.Reliable, -1); AmongUsClient.Instance.FinishRpcImmediately(writer); RPCProcedure.sidekickPromotes(); } } } - - [HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.SetTasks))] - public static class Role - { - public static void Postfix(PlayerControl __instance) - { - if (PlayerControl.LocalPlayer == null) return; - - // Remove default ImportantTextTasks - var toRemove = new List(); - foreach (PlayerTask t in __instance.myTasks) { - if (t.gameObject.GetComponent() != null) { - toRemove.Add(t); - } - } - foreach (PlayerTask t in toRemove) - __instance.RemoveTask(t); - - // Add description - RoleInfo roleInfo = RoleInfo.getRoleInfoForPlayer(__instance); - var task = new GameObject("RoleTask").AddComponent(); - task.transform.SetParent(__instance.transform, false); - - if (__instance == Jackal.jackal) { - var getSidekickText = Jackal.canCreateSidekick ? " and recruit a Sidekick" : ""; - task.Text = $"{roleInfo.colorHexString()}{roleInfo.name}: Kill everyone{getSidekickText}"; - } else { - task.Text = $"{roleInfo.colorHexString()}{roleInfo.name}: {roleInfo.shortDescription}"; - } - - __instance.myTasks.Insert(0, task); - } - } } diff --git a/Source Code/RPC.cs b/Source Code/RPC.cs index 39cf9e2..7cd28cb 100644 --- a/Source Code/RPC.cs +++ b/Source Code/RPC.cs @@ -3,12 +3,19 @@ using Hazel; using static TheOtherRoles.TheOtherRoles; using static TheOtherRoles.HudManagerStartPatch; using static TheOtherRoles.GameHistory; +using static TheOtherRoles.MapOptions; using System.Collections.Generic; using System.Collections; using System.Linq; using UnityEngine; using System; +using Palette = GLNPIJPGGNJ; +using DeathReason = KAPJFCMEBJE; +using SwitchSystem = FNEHFOPHPJO; +using SystemTypes = LGBKLKNAINN; +using Effects = HLPCBNMDEHF; + namespace TheOtherRoles { enum RoleId { @@ -30,14 +37,15 @@ namespace TheOtherRoles Seer, Morphling, Camouflager, - Spy, + Hacker, Child, BountyHunter, Tracker, Vampire, Snitch, Jackal, - Sidekick + Sidekick, + Eraser } enum CustomRPC @@ -45,35 +53,39 @@ namespace TheOtherRoles // Main Controls ResetVaribles = 50, - ForceEnd = 51, - SetRole = 52, + ShareOptionSelection, + ForceEnd, + SetRole, // Role functionality JesterBountyHunterWin = 80, - EngineerFixLights = 81, - EngineerUsedRepair = 82, - JanitorClean = 83, - SheriffKill = 84, - TimeMasterRewindTime = 85, - MedicSetShielded = 86, - ShieldedMurderAttempt = 87, - TimeMasterRevive = 88, - ShifterShift = 89, - SwapperSwap = 90, - SeerReveal = 91, - MorphlingMorph = 92, - CamouflagerCamouflage = 93, - TrackerUsedTracker = 94, - LoverSuicide = 95, - SetBountyHunterTarget = 96, - VampireBiteNotification = 97, - VampireTryKill = 98, - PlaceGarlic = 99, - JackalKill = 100, - SidekickKill = 101, - JackalCreatesSidekick = 102, - SidekickPromotes = 103 + EngineerFixLights, + EngineerUsedRepair, + JanitorClean, + SheriffKill, + MedicSetShielded, + ShieldedMurderAttempt, + TimeMasterShield, + TimeMasterRewindTime, + ShifterShift, + SwapperSwap, + MorphlingMorph, + CamouflagerCamouflage, + TrackerUsedTracker, + LoverSuicide, + SetBountyHunterTarget, + VampireSetBitten, + VampireTryKill, + PlaceGarlic, + JackalKill, + SidekickKill, + JackalCreatesSidekick, + SidekickPromotes, + ChildLose, + ErasePlayerRole, + SetFutureErased, + SetFutureShifted } public static class RPCProcedure { @@ -82,19 +94,25 @@ namespace TheOtherRoles public static void resetVariables() { Garlic.clearGarlics(); + clearAndReloadMapOptions(); clearAndReloadRoles(); clearGameHistory(); setCustomButtonCooldowns(); } + public static void shareOptionSelection(uint id, uint selection) { + CustomOption option = CustomOption.options.FirstOrDefault(option => option.id == (int)id); + option.updateSelection((int)selection); + } + public static void forceEnd() { foreach (PlayerControl player in PlayerControl.AllPlayerControls) { - if (!player.Data.IsImpostor) + if (!player.IDOFAMCIJKE.CIDDOFDJHJH) { player.RemoveInfected(); player.MurderPlayer(player); - player.Data.IsDead = true; + player.IDOFAMCIJKE.FGNJJFABIHJ = true; } } } @@ -157,8 +175,8 @@ namespace TheOtherRoles case RoleId.Camouflager: Camouflager.camouflager = player; break; - case RoleId.Spy: - Spy.spy = player; + case RoleId.Hacker: + Hacker.hacker = player; break; case RoleId.Child: Child.child = player; @@ -181,6 +199,9 @@ namespace TheOtherRoles case RoleId.Sidekick: Sidekick.sidekick = player; break; + case RoleId.Eraser: + Eraser.eraser = player; + break; } } } @@ -196,12 +217,12 @@ namespace TheOtherRoles if (Jester.jester != null && exiled == Jester.jester) { Jester.jester.Revive(); - Jester.jester.Data.IsDead = false; - Jester.jester.Data.IsImpostor = true; + Jester.jester.IDOFAMCIJKE.FGNJJFABIHJ = false; + Jester.jester.IDOFAMCIJKE.CIDDOFDJHJH = true; jesterWin = true; } - if (BountyHunter.bountyHunter != null && !BountyHunter.bountyHunter.Data.IsDead && BountyHunter.target == exiled) { - BountyHunter.bountyHunter.Data.IsImpostor = true; + if (BountyHunter.bountyHunter != null && !BountyHunter.bountyHunter.IDOFAMCIJKE.FGNJJFABIHJ && BountyHunter.target == exiled) { + BountyHunter.bountyHunter.IDOFAMCIJKE.CIDDOFDJHJH = true; bountyHunterWin = true; } @@ -211,26 +232,26 @@ namespace TheOtherRoles { player.RemoveInfected(); player.Die(DeathReason.Exile); - player.Data.IsDead = true; - player.Data.IsImpostor = false; + player.IDOFAMCIJKE.FGNJJFABIHJ = true; + player.IDOFAMCIJKE.CIDDOFDJHJH = false; } } if (jesterWin && !bountyHunterWin && BountyHunter.bountyHunter != null) { BountyHunter.bountyHunter.RemoveInfected(); BountyHunter.bountyHunter.Die(DeathReason.Exile); - BountyHunter.bountyHunter.Data.IsDead = true; - BountyHunter.bountyHunter.Data.IsImpostor = false; + BountyHunter.bountyHunter.IDOFAMCIJKE.FGNJJFABIHJ = true; + BountyHunter.bountyHunter.IDOFAMCIJKE.CIDDOFDJHJH = false; } else if (bountyHunterWin && !jesterWin && Jester.jester != null) { Jester.jester.RemoveInfected(); Jester.jester.Die(DeathReason.Exile); - Jester.jester.Data.IsDead = true; - Jester.jester.Data.IsImpostor = false; + Jester.jester.IDOFAMCIJKE.FGNJJFABIHJ = true; + Jester.jester.IDOFAMCIJKE.CIDDOFDJHJH = false; } } public static void engineerFixLights() { SwitchSystem switchSystem = ShipStatus.Instance.Systems[SystemTypes.Electrical].Cast(); - switchSystem.ActualSwitches = switchSystem.ExpectedSwitches; + switchSystem.GNPBPJHLPAO = switchSystem.KNFBDAFFMGF; } public static void engineerUsedRepair() { @@ -240,7 +261,7 @@ namespace TheOtherRoles public static void janitorClean(byte playerId) { DeadBody[] array = UnityEngine.Object.FindObjectsOfType(); for (int i = 0; i < array.Length; i++) { - if (GameData.Instance.GetPlayerById(array[i].ParentId).PlayerId == playerId) + if (GameData.Instance.GetPlayerById(array[i].ParentId).GMBAIPNOKLP == playerId) UnityEngine.Object.Destroy(array[i].gameObject); } } @@ -257,15 +278,21 @@ namespace TheOtherRoles } public static void timeMasterRewindTime() { + HudManager.CMJOLNCMAPD.FullScreen.color = new Color(0f, 0.5f, 0.8f, 0.3f); + HudManager.CMJOLNCMAPD.FullScreen.enabled = true; + PlayerControl.LocalPlayer.StartCoroutine(Effects.LDACHPMFOIF(TimeMaster.rewindTime / 2, new Action((p) => { + if (p == 1f) HudManager.CMJOLNCMAPD.FullScreen.enabled = false; + }))); + if (TimeMaster.timeMaster == null) return; PlayerControl lp = PlayerControl.LocalPlayer; - if (lp?.Data != null && !lp.Data.IsDead && lp.inVent) { + if (lp?.IDOFAMCIJKE != null && !lp.IDOFAMCIJKE.FGNJJFABIHJ && lp.inVent) { if ((float)(DateTime.UtcNow -localVentEnterTimePoint).TotalMilliseconds < 1000 * TimeMaster.rewindTime) { - foreach (Vent vent in ShipStatus.Instance.AllVents) { + foreach (Vent vent in ShipStatus.Instance.GIDPCPOEFBC) { bool canUse; bool couldUse; - vent.CanUse(PlayerControl.LocalPlayer.Data, out canUse, out couldUse); + vent.CanUse(PlayerControl.LocalPlayer.IDOFAMCIJKE, out canUse, out couldUse); if (canUse) { PlayerControl.LocalPlayer.MyPhysics.RpcExitVent(vent.Id); vent.SetButtons(false); @@ -283,8 +310,13 @@ namespace TheOtherRoles if (Minigame.Instance) Minigame.Instance.ForceClose(); PlayerControl.LocalPlayer.moveable = false; - HudManager.Instance.FullScreen.color = new Color(0f, 0.5f, 0.8f, 0.3f); - HudManager.Instance.FullScreen.enabled = true; + } + + public static void timeMasterShield() { + TimeMaster.shieldActive = true; + PlayerControl.LocalPlayer.StartCoroutine(Effects.LDACHPMFOIF(TimeMaster.shieldDuration, new Action((p) => { + if (p == 1f) TimeMaster.shieldActive = false; + }))); } public static void medicSetShielded(byte shieldedId) { @@ -295,100 +327,87 @@ namespace TheOtherRoles } public static void shieldedMurderAttempt() { - if (Medic.shielded != null && Medic.shielded == PlayerControl.LocalPlayer && Medic.showAttemptToShielded && HudManager.Instance?.FullScreen != null) { - Color c = Palette.ImpostorRed; - HudManager.Instance.FullScreen.enabled = true; - Reactor.Coroutines.Start(Helpers.CoFlashAndDisable( - HudManager.Instance.FullScreen, - 0.5f, - new Color(c.r, c.g, c.b, 0f), - new Color(c.r, c.g, c.b, 0.75f) - )); + if (Medic.shielded != null && Medic.shielded == PlayerControl.LocalPlayer && Medic.showAttemptToShielded && HudManager.CMJOLNCMAPD?.FullScreen != null) { + HudManager.CMJOLNCMAPD.FullScreen.enabled = true; + HudManager.CMJOLNCMAPD.StartCoroutine(Effects.LDACHPMFOIF(0.5f, new Action((p) => { + var renderer = HudManager.CMJOLNCMAPD.FullScreen; + Color c = Palette.LDCHDOFJPGH; + if (p < 0.5) { + if (renderer != null) + renderer.color = new Color(c.r, c.g, c.b, Mathf.Clamp01(p * 2 * 0.75f)); + } else { + if (renderer != null) + renderer.color = new Color(c.r, c.g, c.b, Mathf.Clamp01((1-p) * 2 * 0.75f)); + } + if (p == 1f && renderer != null) renderer.enabled = false; + }))); } } - public static void timeMasterRevive(byte playerId) { - foreach (PlayerControl player in PlayerControl.AllPlayerControls) - if (player.PlayerId == playerId) { - player.Revive(); - var body = UnityEngine.Object.FindObjectsOfType().FirstOrDefault(b => b.ParentId == playerId); - DeadPlayer deadPlayerEntry = deadPlayers.Where(x => x.player.PlayerId == playerId).FirstOrDefault(); - if (body != null) UnityEngine.Object.Destroy(body.gameObject); - if (deadPlayerEntry != null) deadPlayers.Remove(deadPlayerEntry); - } - } - public static void shifterShift(byte targetId) { - foreach (PlayerControl player in PlayerControl.AllPlayerControls) - { - if (player.PlayerId == targetId && Shifter.shifter != null) - { - // Suicide when impostor or impostor variants - if (player.Data.IsImpostor || player == Jackal.jackal || player == Sidekick.sidekick) { - Shifter.shifter.MurderPlayer(Shifter.shifter); - return; - } + PlayerControl oldShifter = Shifter.shifter; + PlayerControl player = Helpers.playerById(targetId); + if (player == null || oldShifter == null) return; - PlayerControl oldShifter = Shifter.shifter; - // Switch tasks - var shifterSabotageTasks = oldShifter.myTasks; - oldShifter.myTasks = player.myTasks; - player.myTasks = shifterSabotageTasks; - - // Switch shield - if (Medic.shielded != null && Medic.shielded == player) { - Medic.shielded.myRend.material.SetFloat("_Outline", 0f); - Medic.shielded = oldShifter; - } else if (Medic.shielded != null && Medic.shielded == oldShifter) { - Medic.shielded.myRend.material.SetFloat("_Outline", 0f); - Medic.shielded = player; - } + Shifter.futureShift = null; + Shifter.clearAndReload(); - // Shift role - if (Jester.jester != null && Jester.jester == player) { - Jester.jester = oldShifter; - } else if (Mayor.mayor != null && Mayor.mayor == player) { - Mayor.mayor = oldShifter; - } else if (Engineer.engineer != null && Engineer.engineer == player) { - Engineer.engineer = oldShifter; - } else if (Sheriff.sheriff != null && Sheriff.sheriff == player) { - Sheriff.sheriff = oldShifter; - } else if (Lighter.lighter != null && Lighter.lighter == player) { - Lighter.lighter = oldShifter; - } else if (Detective.detective != null && Detective.detective == player) { - Detective.detective = oldShifter; - } else if (TimeMaster.timeMaster != null && TimeMaster.timeMaster == player) { - TimeMaster.timeMaster = oldShifter; - } else if (Medic.medic != null && Medic.medic == player) { - Medic.medic = oldShifter; - } else if (Swapper.swapper != null && Swapper.swapper == player) { - Swapper.swapper = oldShifter; - } else if (Lovers.lover1 != null && Lovers.lover1 == player) { - Lovers.lover1 = oldShifter; - } else if (Lovers.lover2 != null && Lovers.lover2 == player) { - Lovers.lover2 = oldShifter; - } else if (Seer.seer != null && Seer.seer == player) { - Seer.seer = oldShifter; - } else if (Spy.spy != null && Spy.spy == player) { - Spy.spy = oldShifter; - } else if (Child.child != null && Child.child == player) { - Child.child = oldShifter; - } else if (BountyHunter.bountyHunter != null && BountyHunter.bountyHunter == player) { - BountyHunter.bountyHunter = oldShifter; - } else if (Tracker.tracker != null && Tracker.tracker == player) { - Tracker.tracker = oldShifter; - } else if (Snitch.snitch != null && Snitch.snitch == player) { - Snitch.snitch = oldShifter; - }else { // Crewmate - } - - Shifter.shifter = player; + // Suicide (exile) when impostor or impostor variants + if (player.IDOFAMCIJKE.CIDDOFDJHJH || player == Jackal.jackal || player == Sidekick.sidekick) { + oldShifter.Exiled(); + return; + } - // Set cooldowns to max for both players - if (PlayerControl.LocalPlayer == Shifter.shifter || PlayerControl.LocalPlayer == oldShifter) - CustomButton.ResetAllCooldowns(); - } + // Switch shield + if (Medic.shielded != null && Medic.shielded == player) { + Medic.shielded.LNMJKMLHMIM.material.SetFloat("_Outline", 0f); + Medic.shielded = oldShifter; + } else if (Medic.shielded != null && Medic.shielded == oldShifter) { + Medic.shielded.LNMJKMLHMIM.material.SetFloat("_Outline", 0f); + Medic.shielded = player; } + + // Shift role + if (Jester.jester != null && Jester.jester == player) { + Jester.jester = oldShifter; + } else if (Mayor.mayor != null && Mayor.mayor == player) { + Mayor.mayor = oldShifter; + } else if (Engineer.engineer != null && Engineer.engineer == player) { + Engineer.engineer = oldShifter; + } else if (Sheriff.sheriff != null && Sheriff.sheriff == player) { + Sheriff.sheriff = oldShifter; + } else if (Lighter.lighter != null && Lighter.lighter == player) { + Lighter.lighter = oldShifter; + } else if (Detective.detective != null && Detective.detective == player) { + Detective.detective = oldShifter; + } else if (TimeMaster.timeMaster != null && TimeMaster.timeMaster == player) { + TimeMaster.timeMaster = oldShifter; + } else if (Medic.medic != null && Medic.medic == player) { + Medic.medic = oldShifter; + } else if (Swapper.swapper != null && Swapper.swapper == player) { + Swapper.swapper = oldShifter; + } else if (Lovers.lover1 != null && Lovers.lover1 == player) { + Lovers.lover1 = oldShifter; + } else if (Lovers.lover2 != null && Lovers.lover2 == player) { + Lovers.lover2 = oldShifter; + } else if (Seer.seer != null && Seer.seer == player) { + Seer.seer = oldShifter; + } else if (Hacker.hacker != null && Hacker.hacker == player) { + Hacker.hacker = oldShifter; + } else if (Child.child != null && Child.child == player) { + Child.child = oldShifter; + } else if (BountyHunter.bountyHunter != null && BountyHunter.bountyHunter == player) { + BountyHunter.bountyHunter = oldShifter; + } else if (Tracker.tracker != null && Tracker.tracker == player) { + Tracker.tracker = oldShifter; + } else if (Snitch.snitch != null && Snitch.snitch == player) { + Snitch.snitch = oldShifter; + }else { // Crewmate + } + + // Set cooldowns to max for both players + if (PlayerControl.LocalPlayer == oldShifter || PlayerControl.LocalPlayer == player) + CustomButton.ResetAllCooldowns(); } public static void swapperSwap(byte playerId1, byte playerId2) { @@ -398,36 +417,6 @@ namespace TheOtherRoles } } - public static void seerReveal(byte targetId, byte targetOrMistakeId) { - if (Seer.seer == null) return; - - PlayerControl target = Helpers.playerById(targetId); - PlayerControl targetOrMistake = Helpers.playerById(targetOrMistakeId); - - if (target != null && targetOrMistake != null && !Seer.revealedPlayers.Keys.Any(p => p.Data.PlayerId == targetId)) { - Seer.revealedPlayers.Add(target, targetOrMistake); - - if (PlayerControl.LocalPlayer == target && HudManager.Instance?.FullScreen != null) { - RoleInfo si = RoleInfo.getRoleInfoForPlayer(target); // Use RoleInfo of target here, because we need the isGood of the targets role - bool showNotification = false; - if (Seer.playersWithNotification == 0 ) showNotification = true; - else if (Seer.playersWithNotification == 1 && si.isGood) showNotification = true; - else if (Seer.playersWithNotification == 2 && !si.isGood) showNotification = true; - else if (Seer.playersWithNotification == 3) showNotification = false; - - if (showNotification) { - HudManager.Instance.FullScreen.enabled = true; - Reactor.Coroutines.Start(Helpers.CoFlashAndDisable( - HudManager.Instance.FullScreen, - 0.5f, - new Color(42f / 255f, 187f / 255f, 245f / 255f, 0f), - new Color(42f / 255f, 187f / 255f, 245f / 255f, 0.75f) - )); - } - } - } - } - public static void morphlingMorph(byte playerId) { PlayerControl target = Helpers.playerById(playerId); if (Morphling.morphling == null || target == null) return; @@ -443,9 +432,9 @@ namespace TheOtherRoles } public static void loverSuicide(byte remainingLoverId) { - if (Lovers.lover1 != null && !Lovers.lover1.Data.IsDead && Lovers.lover1.PlayerId == remainingLoverId) { + if (Lovers.lover1 != null && !Lovers.lover1.IDOFAMCIJKE.FGNJJFABIHJ && Lovers.lover1.PlayerId == remainingLoverId) { Lovers.lover1.MurderPlayer(Lovers.lover1); - } else if (Lovers.lover2 != null && !Lovers.lover2.Data.IsDead && Lovers.lover2.PlayerId == remainingLoverId) { + } else if (Lovers.lover2 != null && !Lovers.lover2.IDOFAMCIJKE.FGNJJFABIHJ && Lovers.lover2.PlayerId == remainingLoverId) { Lovers.lover2.MurderPlayer(Lovers.lover2); } } @@ -456,19 +445,22 @@ namespace TheOtherRoles BountyHunter.target = player; } - public static void vampireBiteNotification(byte targetId) { + public static void vampireSetBitten(byte targetId, byte reset) { + if (reset != 0) { + Vampire.bitten = null; + return; + } + if (Vampire.vampire == null) return; foreach (PlayerControl player in PlayerControl.AllPlayerControls) { - if (player.PlayerId == targetId && !player.Data.IsDead) { + if (player.PlayerId == targetId && !player.IDOFAMCIJKE.FGNJJFABIHJ) { Vampire.bitten = player; } } } public static void vampireTryKill() { - if (Vampire.vampire == null || Vampire.bitten == null) return; - - if (!Vampire.bitten.Data.IsDead && Helpers.handleMurderAttempt(Vampire.bitten, false)) { + if (Vampire.bitten != null && !Vampire.bitten.IDOFAMCIJKE.FGNJJFABIHJ) { Vampire.vampire.MurderPlayer(Vampire.bitten); } Vampire.bitten = null; @@ -515,52 +507,15 @@ namespace TheOtherRoles { if (player.PlayerId == targetId) { - if(!Jackal.canCreateSidekickFromImpostor && player.Data.IsImpostor) { + if(!Jackal.canCreateSidekickFromImpostor && player.IDOFAMCIJKE.CIDDOFDJHJH) { Jackal.fakeSidekick = player; return; } - Sidekick.sidekick = player; player.RemoveInfected(); - - // Crewmate roles - if(player == Jester.jester) Jester.clearAndReload(); - if(player == Mayor.mayor) Mayor.clearAndReload(); - if(player == Engineer.engineer) Engineer.clearAndReload(); - if(player == Sheriff.sheriff) Sheriff.clearAndReload(); - if(player == Lighter.lighter) Lighter.clearAndReload(); - if(player == Detective.detective) Detective.clearAndReload(); - if(player == TimeMaster.timeMaster) TimeMaster.clearAndReload(); - if(player == Medic.medic) Medic.clearAndReload(); - if(player == Shifter.shifter) Shifter.clearAndReload(); - if(player == Seer.seer) Seer.clearAndReload(); - if(player == Spy.spy) Spy.clearAndReload(); - if(player == Child.child) Child.clearAndReload(); - if(player == Tracker.tracker) Tracker.clearAndReload(); - if(player == BountyHunter.bountyHunter) BountyHunter.clearAndReload(); - if(player == Snitch.snitch) Snitch.clearAndReload(); - if(player == Swapper.swapper) Swapper.clearAndReload(); - - // Impostor roles - if(player == Morphling.morphling) Morphling.clearAndReload(); - if(player == Camouflager.camouflager) Camouflager.clearAndReload(); - if(player == Godfather.godfather) Godfather.clearAndReload(); - if(player == Mafioso.mafioso) Mafioso.clearAndReload(); - if(player == Janitor.janitor) Janitor.clearAndReload(); - if(player == Vampire.vampire) Vampire.clearAndReload(); - - // The Sidekick stays a part of the lover couple! + if (player != Lovers.lover1 && player != Lovers.lover2) erasePlayerRole(player.PlayerId); - if (PlayerControl.LocalPlayer == null) return; - if (PlayerControl.LocalPlayer == player) { - //Only the Lover keeps his ImportantTextTask - Helpers.removeTasksFromPlayer(player, player != Lovers.lover1 && player != Lovers.lover2); - - var task = new GameObject("RoleTask").AddComponent(); - task.transform.SetParent(player.transform, false); - task.Text = "[00B4EBFF]Sidekick: Help your Jackal to kill everyone"; - player.myTasks.Insert(0, task); - } - + Sidekick.sidekick = player; + Helpers.removeTasksFromPlayer(player); return; } } @@ -574,26 +529,76 @@ namespace TheOtherRoles Jackal.canCreateSidekick = false; } Sidekick.clearAndReload(); - if (PlayerControl.LocalPlayer == null) return; - if (PlayerControl.LocalPlayer == player) { - Helpers.removeTasksFromPlayer(player, true); - var textTask = new GameObject("RoleTask").AddComponent(); - textTask.transform.SetParent(player.transform, false); - var getSidekickText = Jackal.canCreateSidekick ? " and recruit a Sidekick" : ""; - textTask.Text = $"[00B4EBFF]Jackal: Kill everyone{getSidekickText}"; - player.myTasks.Insert(0, textTask); - } return; } + + public static void childLose() { + Child.triggerChildLose = true; + } + + public static void erasePlayerRole(byte playerId) { + PlayerControl player = Helpers.playerById(playerId); + if (player == null) return; + + // Crewmate roles + if (player == Mayor.mayor) Mayor.clearAndReload(); + if (player == Engineer.engineer) Engineer.clearAndReload(); + if (player == Sheriff.sheriff) Sheriff.clearAndReload(); + if (player == Lighter.lighter) Lighter.clearAndReload(); + if (player == Detective.detective) Detective.clearAndReload(); + if (player == TimeMaster.timeMaster) TimeMaster.clearAndReload(); + if (player == Medic.medic) Medic.clearAndReload(); + if (player == Shifter.shifter) Shifter.clearAndReload(); + if (player == Seer.seer) Seer.clearAndReload(); + if (player == Hacker.hacker) Hacker.clearAndReload(); + if (player == Child.child) Child.clearAndReload(); + if (player == Tracker.tracker) Tracker.clearAndReload(); + if (player == BountyHunter.bountyHunter) BountyHunter.clearAndReload(); + if (player == Snitch.snitch) Snitch.clearAndReload(); + if (player == Swapper.swapper) Swapper.clearAndReload(); + + // Impostor roles + if (player == Morphling.morphling) Morphling.clearAndReload(); + if (player == Camouflager.camouflager) Camouflager.clearAndReload(); + if (player == Godfather.godfather) Godfather.clearAndReload(); + if (player == Mafioso.mafioso) Mafioso.clearAndReload(); + if (player == Janitor.janitor) Janitor.clearAndReload(); + if (player == Vampire.vampire) Vampire.clearAndReload(); + if (player == Eraser.eraser) Eraser.clearAndReload(); + + // Other roles + if (player == Jester.jester) Jester.clearAndReload(); + if (player == Lovers.lover1 || player == Lovers.lover2) { // The whole Lover couple is being erased + Lovers.clearAndReload(); + } + if (player == Jackal.jackal) { // Promote Sidekick and hence override the the Jackal or erase Jackal + if (Sidekick.promotesToJackal && Sidekick.sidekick != null && !Sidekick.sidekick.IDOFAMCIJKE.FGNJJFABIHJ) { + RPCProcedure.sidekickPromotes(); + } else { + Jackal.clearAndReload(); + } + } + if (player == Sidekick.sidekick) Sidekick.clearAndReload(); + } + + public static void setFutureErased(byte playerId) { + PlayerControl player = Helpers.playerById(playerId); + if (Eraser.futureErased == null) Eraser.futureErased = new List(); + if (player != null) Eraser.futureErased.Add(player); + } + + public static void setFutureShifted(byte playerId) { + Shifter.futureShift = Helpers.playerById(playerId); + } } [HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.HandleRpc))] class RPCHandlerPatch { - static void Postfix(byte ACCJCEHMKLN, MessageReader HFPCBBHJIPJ) + static void Postfix(byte GIICFHKILOB, MessageReader DOOILGKLBBF) { - byte packetId = ACCJCEHMKLN; - MessageReader reader = HFPCBBHJIPJ; + byte packetId = GIICFHKILOB; + MessageReader reader = DOOILGKLBBF; switch (packetId) { // Main Controls @@ -601,12 +606,17 @@ namespace TheOtherRoles case (byte)CustomRPC.ResetVaribles: RPCProcedure.resetVariables(); break; + case (byte)CustomRPC.ShareOptionSelection: + uint id = DOOILGKLBBF.ReadPackedUInt32(); + uint selection = DOOILGKLBBF.ReadPackedUInt32(); + RPCProcedure.shareOptionSelection(id, selection); + break; case (byte)CustomRPC.ForceEnd: RPCProcedure.forceEnd(); break; case (byte)CustomRPC.SetRole: - byte roleId = HFPCBBHJIPJ.ReadByte(); - byte playerId = HFPCBBHJIPJ.ReadByte(); + byte roleId = DOOILGKLBBF.ReadByte(); + byte playerId = DOOILGKLBBF.ReadByte(); RPCProcedure.setRole(roleId, playerId); break; @@ -614,7 +624,7 @@ namespace TheOtherRoles // Role functionality case (byte)CustomRPC.JesterBountyHunterWin: - RPCProcedure.jesterBountyHunterWin(HFPCBBHJIPJ.ReadByte()); + RPCProcedure.jesterBountyHunterWin(DOOILGKLBBF.ReadByte()); break; case (byte)CustomRPC.EngineerFixLights: RPCProcedure.engineerFixLights(); @@ -623,72 +633,81 @@ namespace TheOtherRoles RPCProcedure.engineerUsedRepair(); break; case (byte)CustomRPC.JanitorClean: - RPCProcedure.janitorClean(HFPCBBHJIPJ.ReadByte()); + RPCProcedure.janitorClean(DOOILGKLBBF.ReadByte()); break; case (byte)CustomRPC.SheriffKill: - RPCProcedure.sheriffKill(HFPCBBHJIPJ.ReadByte()); + RPCProcedure.sheriffKill(DOOILGKLBBF.ReadByte()); break; case (byte)CustomRPC.TimeMasterRewindTime: RPCProcedure.timeMasterRewindTime(); break; + case (byte)CustomRPC.TimeMasterShield: + RPCProcedure.timeMasterShield(); + break; case (byte)CustomRPC.MedicSetShielded: - RPCProcedure.medicSetShielded(HFPCBBHJIPJ.ReadByte()); + RPCProcedure.medicSetShielded(DOOILGKLBBF.ReadByte()); break; case (byte)CustomRPC.ShieldedMurderAttempt: RPCProcedure.shieldedMurderAttempt(); break; - case (byte)CustomRPC.TimeMasterRevive: - RPCProcedure.timeMasterRevive(HFPCBBHJIPJ.ReadByte()); - break; case (byte)CustomRPC.ShifterShift: - RPCProcedure.shifterShift(HFPCBBHJIPJ.ReadByte()); + RPCProcedure.shifterShift(DOOILGKLBBF.ReadByte()); break; case (byte)CustomRPC.SwapperSwap: - byte playerId1 = HFPCBBHJIPJ.ReadByte(); - byte playerId2 = HFPCBBHJIPJ.ReadByte(); + byte playerId1 = DOOILGKLBBF.ReadByte(); + byte playerId2 = DOOILGKLBBF.ReadByte(); RPCProcedure.swapperSwap(playerId1, playerId2); break; - case (byte)CustomRPC.SeerReveal: - byte targetId = HFPCBBHJIPJ.ReadByte(); - byte targetOrMistakeId = HFPCBBHJIPJ.ReadByte(); - RPCProcedure.seerReveal(targetId, targetOrMistakeId); - break; case (byte)CustomRPC.MorphlingMorph: - RPCProcedure.morphlingMorph(HFPCBBHJIPJ.ReadByte()); + RPCProcedure.morphlingMorph(DOOILGKLBBF.ReadByte()); break; case (byte)CustomRPC.CamouflagerCamouflage: RPCProcedure.camouflagerCamouflage(); break; case (byte)CustomRPC.LoverSuicide: - RPCProcedure.loverSuicide(HFPCBBHJIPJ.ReadByte()); + RPCProcedure.loverSuicide(DOOILGKLBBF.ReadByte()); break; case (byte)CustomRPC.SetBountyHunterTarget: - RPCProcedure.setBountyHunterTarget(HFPCBBHJIPJ.ReadByte()); + RPCProcedure.setBountyHunterTarget(DOOILGKLBBF.ReadByte()); break; - case (byte)CustomRPC.VampireBiteNotification: - RPCProcedure.vampireBiteNotification(HFPCBBHJIPJ.ReadByte()); + case (byte)CustomRPC.VampireSetBitten: + byte bittenId = DOOILGKLBBF.ReadByte(); + byte reset = DOOILGKLBBF.ReadByte(); + RPCProcedure.vampireSetBitten(bittenId, reset); break; case (byte)CustomRPC.VampireTryKill: RPCProcedure.vampireTryKill(); break; case (byte)CustomRPC.PlaceGarlic: - RPCProcedure.placeGarlic(HFPCBBHJIPJ.ReadBytesAndSize()); + RPCProcedure.placeGarlic(DOOILGKLBBF.ReadBytesAndSize()); break; case (byte)CustomRPC.TrackerUsedTracker: - RPCProcedure.trackerUsedTracker(HFPCBBHJIPJ.ReadByte()); + RPCProcedure.trackerUsedTracker(DOOILGKLBBF.ReadByte()); break; case (byte)CustomRPC.JackalKill: - RPCProcedure.jackalKill(HFPCBBHJIPJ.ReadByte()); + RPCProcedure.jackalKill(DOOILGKLBBF.ReadByte()); break; case (byte)CustomRPC.SidekickKill: - RPCProcedure.sidekickKill(HFPCBBHJIPJ.ReadByte()); + RPCProcedure.sidekickKill(DOOILGKLBBF.ReadByte()); break; case (byte)CustomRPC.JackalCreatesSidekick: - RPCProcedure.jackalCreatesSidekick(HFPCBBHJIPJ.ReadByte()); + RPCProcedure.jackalCreatesSidekick(DOOILGKLBBF.ReadByte()); break; case (byte)CustomRPC.SidekickPromotes: RPCProcedure.sidekickPromotes(); break; + case (byte)CustomRPC.ChildLose: + RPCProcedure.childLose(); + break; + case (byte)CustomRPC.ErasePlayerRole: + RPCProcedure.erasePlayerRole(DOOILGKLBBF.ReadByte()); + break; + case (byte)CustomRPC.SetFutureErased: + RPCProcedure.setFutureErased(DOOILGKLBBF.ReadByte()); + break; + case (byte)CustomRPC.SetFutureShifted: + RPCProcedure.setFutureShifted(DOOILGKLBBF.ReadByte()); + break; } } } diff --git a/Source Code/RoleAssignmentPatch.cs b/Source Code/RoleAssignmentPatch.cs index 79a20d0..da0a3d2 100644 --- a/Source Code/RoleAssignmentPatch.cs +++ b/Source Code/RoleAssignmentPatch.cs @@ -29,19 +29,19 @@ namespace TheOtherRoles RPCProcedure.setRole(roleId, playerId); } - public static void Postfix(Il2CppReferenceArray FMAOEJEHPAO) + public static void Postfix(Il2CppReferenceArray LBJJHLMFDJL) { MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.ResetVaribles, Hazel.SendOption.Reliable, -1); AmongUsClient.Instance.FinishRpcImmediately(writer); RPCProcedure.resetVariables(); List crewmates = PlayerControl.AllPlayerControls.ToArray().ToList().OrderBy(x => Guid.NewGuid()).ToList(); - crewmates.RemoveAll(x => x.Data.IsImpostor); + crewmates.RemoveAll(x => x.IDOFAMCIJKE.CIDDOFDJHJH); List impostors = PlayerControl.AllPlayerControls.ToArray().ToList().OrderBy(x => Guid.NewGuid()).ToList(); - impostors.RemoveAll(x => !x.Data.IsImpostor); + impostors.RemoveAll(x => !x.IDOFAMCIJKE.CIDDOFDJHJH); - float crewCountSettings = (float)TheOtherRolesPlugin.crewmateRolesCount.GetValue() / 2; - float impCountSettings = (float)TheOtherRolesPlugin.impostorRolesCount.GetValue() / 2; + float crewCountSettings = (float)CustomOptionHolder.crewmateRolesCount.getSelection() / 2; + float impCountSettings = (float)CustomOptionHolder.impostorRolesCount.getSelection() / 2; if (crewCountSettings % 1 == 0.5f) crewCountSettings += 0.5f * (rnd.Next(2) * 2 - 1); if (impCountSettings % 1 == 0.5f) impCountSettings += 0.5f * (rnd.Next(2) * 2 - 1); @@ -52,38 +52,38 @@ namespace TheOtherRoles Dictionary impSettings = new Dictionary(); Dictionary crewSettings = new Dictionary(); - impSettings.Add((byte)RoleId.Morphling, TheOtherRolesPlugin.morphlingSpawnRate.GetValue()); - impSettings.Add((byte)RoleId.Camouflager, TheOtherRolesPlugin.camouflagerSpawnRate.GetValue()); - impSettings.Add((byte)RoleId.Vampire, TheOtherRolesPlugin.vampireSpawnRate.GetValue()); - - crewSettings.Add((byte)RoleId.Jester, TheOtherRolesPlugin.jesterSpawnRate.GetValue()); - crewSettings.Add((byte)RoleId.Mayor, TheOtherRolesPlugin.mayorSpawnRate.GetValue()); - crewSettings.Add((byte)RoleId.Engineer, TheOtherRolesPlugin.engineerSpawnRate.GetValue()); - crewSettings.Add((byte)RoleId.Sheriff, TheOtherRolesPlugin.sheriffSpawnRate.GetValue()); - crewSettings.Add((byte)RoleId.Lighter, TheOtherRolesPlugin.lighterSpawnRate.GetValue()); - crewSettings.Add((byte)RoleId.Detective, TheOtherRolesPlugin.detectiveSpawnRate.GetValue()); - crewSettings.Add((byte)RoleId.TimeMaster, TheOtherRolesPlugin.timeMasterSpawnRate.GetValue()); - crewSettings.Add((byte)RoleId.Medic, TheOtherRolesPlugin.medicSpawnRate.GetValue()); - crewSettings.Add((byte)RoleId.Shifter, TheOtherRolesPlugin.shifterSpawnRate.GetValue()); - crewSettings.Add((byte)RoleId.Swapper,TheOtherRolesPlugin.swapperSpawnRate.GetValue()); - crewSettings.Add((byte)RoleId.Seer, TheOtherRolesPlugin.seerSpawnRate.GetValue()); - crewSettings.Add((byte)RoleId.Spy, TheOtherRolesPlugin.spySpawnRate.GetValue()); - crewSettings.Add((byte)RoleId.Child, TheOtherRolesPlugin.childSpawnRate.GetValue()); - crewSettings.Add((byte)RoleId.Tracker, TheOtherRolesPlugin.trackerSpawnRate.GetValue()); - crewSettings.Add((byte)RoleId.Snitch, TheOtherRolesPlugin.snitchSpawnRate.GetValue()); - crewSettings.Add((byte)RoleId.Jackal, TheOtherRolesPlugin.jackalSpawnRate.GetValue()); - // crewSettings.Add((byte)RoleId.BountyHunter, TheOtherRolesPlugin.bountyHunterSpawnRate.GetValue()); BOUNTY HUNTER - - // Set multiple player roles - if (impostors.Count >= 3 && maxImpostorRoles >= 3 && (rnd.Next(1, 101) <= TheOtherRolesPlugin.mafiaSpawnRate.GetValue() * 10)) { + impSettings.Add((byte)RoleId.Morphling, CustomOptionHolder.morphlingSpawnRate.getSelection()); + impSettings.Add((byte)RoleId.Camouflager, CustomOptionHolder.camouflagerSpawnRate.getSelection()); + impSettings.Add((byte)RoleId.Vampire, CustomOptionHolder.vampireSpawnRate.getSelection()); + impSettings.Add((byte)RoleId.Eraser, CustomOptionHolder.eraserSpawnRate.getSelection()); + + crewSettings.Add((byte)RoleId.Jester, CustomOptionHolder.jesterSpawnRate.getSelection()); + crewSettings.Add((byte)RoleId.Mayor, CustomOptionHolder.mayorSpawnRate.getSelection()); + crewSettings.Add((byte)RoleId.Engineer, CustomOptionHolder.engineerSpawnRate.getSelection()); + crewSettings.Add((byte)RoleId.Sheriff, CustomOptionHolder.sheriffSpawnRate.getSelection()); + crewSettings.Add((byte)RoleId.Lighter, CustomOptionHolder.lighterSpawnRate.getSelection()); + crewSettings.Add((byte)RoleId.Detective, CustomOptionHolder.detectiveSpawnRate.getSelection()); + crewSettings.Add((byte)RoleId.TimeMaster, CustomOptionHolder.timeMasterSpawnRate.getSelection()); + crewSettings.Add((byte)RoleId.Medic, CustomOptionHolder.medicSpawnRate.getSelection()); + crewSettings.Add((byte)RoleId.Shifter, CustomOptionHolder.shifterSpawnRate.getSelection()); + crewSettings.Add((byte)RoleId.Swapper,CustomOptionHolder.swapperSpawnRate.getSelection()); + crewSettings.Add((byte)RoleId.Seer, CustomOptionHolder.seerSpawnRate.getSelection()); + crewSettings.Add((byte)RoleId.Hacker, CustomOptionHolder.hackerSpawnRate.getSelection()); + crewSettings.Add((byte)RoleId.Tracker, CustomOptionHolder.trackerSpawnRate.getSelection()); + crewSettings.Add((byte)RoleId.Snitch, CustomOptionHolder.snitchSpawnRate.getSelection()); + crewSettings.Add((byte)RoleId.Jackal, CustomOptionHolder.jackalSpawnRate.getSelection()); + // crewSettings.Add((byte)RoleId.BountyHunter, CustomOptionHolder.bountyHunterSpawnRate.getSelection()); BOUNTY HUNTER + + // Set special roles + if (impostors.Count >= 3 && maxImpostorRoles >= 3 && (rnd.Next(1, 101) <= CustomOptionHolder.mafiaSpawnRate.getSelection() * 10)) { setRoleToRandomPlayer((byte)RoleId.Godfather, impostors); setRoleToRandomPlayer((byte)RoleId.Janitor, impostors); setRoleToRandomPlayer((byte)RoleId.Mafioso, impostors); maxImpostorRoles -= 3; } - if (rnd.Next(1, 101) <= TheOtherRolesPlugin.loversSpawnRate.GetValue() * 10) { - if (impostors.Count > 0 && crewmates.Count > 0 && maxCrewmateRoles > 0 && maxImpostorRoles > 0 && rnd.Next(1, 101) <= TheOtherRolesPlugin.loversImpLoverRate.GetValue()) { + if (rnd.Next(1, 101) <= CustomOptionHolder.loversSpawnRate.getSelection() * 10) { + if (impostors.Count > 0 && crewmates.Count > 0 && maxCrewmateRoles > 0 && maxImpostorRoles > 0 && rnd.Next(1, 101) <= CustomOptionHolder.loversImpLoverRate.getSelection()) { setRoleToRandomPlayer((byte)RoleId.Lover1, impostors); setRoleToRandomPlayer((byte)RoleId.Lover2, crewmates); maxCrewmateRoles--; @@ -95,6 +95,16 @@ namespace TheOtherRoles } } + if (rnd.Next(1, 101) <= CustomOptionHolder.childSpawnRate.getSelection() * 10) { + if (impostors.Count > 0 && maxImpostorRoles > 0 && rnd.Next(1, 101) <= 33) { + setRoleToRandomPlayer((byte)RoleId.Child, impostors); + maxImpostorRoles--; + } else if (crewmates.Count > 0 && maxCrewmateRoles > 0) { + setRoleToRandomPlayer((byte)RoleId.Child, crewmates); + maxCrewmateRoles--; + } + } + // Set tickets and always active roles List crewTickets = new List(); @@ -144,12 +154,12 @@ namespace TheOtherRoles } } - // if (crewmates.Count > 0 && (rnd.Next(1, 101) <= TheOtherRolesPlugin.bountyHunterSpawnRate.GetValue())) { + // if (crewmates.Count > 0 && (rnd.Next(1, 101) <= CustomOptionHolder.bountyHunterSpawnRate.getSelection())) { // List availableTargets = PlayerControl.AllPlayerControls.ToArray().ToList(); // var bountyHunterIndex = rnd.Next(0, crewmates.Count); // byte bountyHunterId = crewmates[bountyHunterIndex].PlayerId; - // availableTargets.RemoveAll(x => x.Data.IsImpostor || x.PlayerId == bountyHunterId); + // availableTargets.RemoveAll(x => x.IDOFAMCIJKE.CIDDOFDJHJH || x.PlayerId == bountyHunterId); // if (availableTargets.Count > 0) { // byte targetId = availableTargets[rnd.Next(0, availableTargets.Count)].PlayerId; diff --git a/Source Code/RoleInfo.cs b/Source Code/RoleInfo.cs index 860dce9..7d1682d 100644 --- a/Source Code/RoleInfo.cs +++ b/Source Code/RoleInfo.cs @@ -1,8 +1,11 @@ using HarmonyLib; using System; +using System.Collections.Generic; using static TheOtherRoles.TheOtherRoles; using UnityEngine; +using Palette = GLNPIJPGGNJ; + namespace TheOtherRoles { public class RoleInfo { @@ -10,14 +13,12 @@ namespace TheOtherRoles public string name; public string introDescription; public string shortDescription; - public bool isGood; - RoleInfo(Color color, string name, string introDescription, string shortDescription, bool isGood) { + RoleInfo(string name, Color color, string introDescription, string shortDescription) { this.color = color; this.name = name; this.introDescription = introDescription; this.shortDescription = shortDescription; - this.isGood = isGood; } public string colorHexString() { @@ -29,197 +30,181 @@ namespace TheOtherRoles return (byte)(f * 255); } - - public static RoleInfo getRoleInfoForPlayer(PlayerControl p) { - string name = ""; - string introDescription = ""; - string shortDescription = ""; - bool isGood = true; - Color color = Color.white; + public static List getRoleInfoForPlayer(PlayerControl p) { + List infos = new List(); if (Jester.jester != null && p == Jester.jester) { - name = "Jester"; - color = Jester.color; - introDescription = "Get voted out"; - shortDescription = introDescription; - isGood = false; - } - else if (Mayor.mayor != null && p == Mayor.mayor) { - name = "Mayor"; - color = Mayor.color; - introDescription = "Your vote counts twice"; - shortDescription = introDescription; - } - else if (Engineer.engineer != null && p == Engineer.engineer) { - name = "Engineer"; - color = Engineer.color; - introDescription = "Maintain important systems on the ship"; - shortDescription = "Repair the ship"; - } - else if (Sheriff.sheriff != null && p == Sheriff.sheriff) { - name = "Sheriff"; - color = Sheriff.color; - introDescription = "Shoot the [FF1919FF]Impostors"; - shortDescription = "Shoot the Impostors"; - } - else if (Lighter.lighter != null && p == Lighter.lighter) { - name = "Lighter"; - color = Lighter.color; - introDescription = "Your light never goes out"; - shortDescription = introDescription; - } - else if (Godfather.godfather != null && p == Godfather.godfather) { - name = "Godfather"; - color = Godfather.color; - introDescription = "Kill all Crewmates"; - shortDescription = introDescription; - isGood = false; - } - else if (Mafioso.mafioso != null && p == Mafioso.mafioso) { - name = "Mafioso"; - color = Mafioso.color; - introDescription = "Work with the [FF1919FF]Mafia[] to kill the Crewmates"; - shortDescription = "Kill all Crewmates"; - isGood = false; - } - else if (Janitor.janitor != null && p == Janitor.janitor) { - name = "Janitor"; - color = Janitor.color; - introDescription = "Work with the [FF1919FF]Mafia[] by hiding dead bodies"; - shortDescription = "Hide dead bodies"; - isGood = false; - } - else if (Morphling.morphling != null && p == Morphling.morphling) { - name = "Morphling"; - color = Morphling.color; - introDescription = "Change your look to not get caught"; - shortDescription = "Change your look"; - isGood = false; - } - else if (Camouflager.camouflager != null && p == Camouflager.camouflager) { - name = "Camouflager"; - color = Camouflager.color; - introDescription = "Camouflage and kill the Crewmates"; - shortDescription = "Hide among others"; - isGood = false; - } - else if (Vampire.vampire != null && p == Vampire.vampire) { - name = "Vampire"; - color = Vampire.color; - introDescription = "Kill the Crewmates with your bites"; - shortDescription = "Bite your enemies"; - isGood = false; - } - else if (Detective.detective != null && p == Detective.detective) { - name = "Detective"; - color = Detective.color; - introDescription = "Find the [FF1919FF]Impostors[] by examining footprints"; - shortDescription = "Examine footprints"; - } - else if (TimeMaster.timeMaster != null && p == TimeMaster.timeMaster) { - name = "Time Master"; - color = TimeMaster.color; - introDescription = "Rewind time to find the [FF1919FF]Impostors"; - shortDescription = "Rewind time"; - } - else if (Medic.medic != null && p == Medic.medic) { - name = "Medic"; - color = Medic.color; - introDescription = "Protect someone with your shield"; - shortDescription = "Protect other players"; - } - else if (Shifter.shifter != null && p == Shifter.shifter) { - name = "Shifter"; - color = Shifter.color; - introDescription = "Shift your role before the game ends"; - shortDescription = "Shift your role"; - isGood = false; - } - else if (Swapper.swapper != null && p == Swapper.swapper) { - name = "Swapper"; - color = Swapper.color; - introDescription = "Swap votes to exile the [FF1919FF]Impostors"; - shortDescription = "Swap votes"; - } - else if (Seer.seer != null && p == Seer.seer) { - name = "Seer"; - color = Seer.color; - introDescription = "Reveal the intentions of everyone on the ship"; - shortDescription = "Reveal all roles"; - } - else if (Spy.spy != null && p == Spy.spy) { - name = "Spy"; - color = Spy.color; - introDescription = "Spy on everyone to find the [FF1919FF]Impostors"; - shortDescription = "Spy on everyone"; - } - else if (Child.child != null && p == Child.child) { - name = "Child"; - color = Child.color; - introDescription = "No one will harm you until you grow up"; - shortDescription = "No one will harm you"; - } - else if (BountyHunter.bountyHunter != null && p == BountyHunter.bountyHunter) { - name = "Bounty Hunter"; - color = BountyHunter.color; - introDescription = "Hunt your bounty down"; - shortDescription = "Hunt your bounty"; - isGood = false; - } - else if (Tracker.tracker != null && p == Tracker.tracker) { - name = "Tracker"; - color = Tracker.color; - introDescription = "Track the [FF1919FF]Impostors[] down"; - shortDescription = "Track the Impostors down"; - } - else if (Snitch.snitch != null && p == Snitch.snitch) { - name = "Snitch"; - color = Snitch.color; - introDescription = "Finish your tasks to find the [FF1919FF]Impostors[]"; - shortDescription = "Finish your tasks"; - } - else if (Jackal.jackal != null && p == Jackal.jackal) { - name = "Jackal"; - color = Jackal.color; - introDescription = "Kill all Crewmates and [FF1919FF]Impostors[FFFFFFFF] to win"; - shortDescription = ""; - isGood = false; - } - else if (Sidekick.sidekick != null && p == Sidekick.sidekick) { - name = "Sidekick"; - color = Sidekick.color; - introDescription = ""; - shortDescription = "Help your Jackal to kill everyone"; - isGood = false; - } - else if ((Lovers.lover1 != null && p == Lovers.lover1) || (Lovers.lover2 != null && p == Lovers.lover2)) { - name = p.Data.IsImpostor ? "ImpLover" : "Lover"; - color = p.Data.IsImpostor ? Palette.ImpostorRed : Lovers.color; - introDescription = "You are in [FC03BEFF]Love[]"; - shortDescription = "You are in love"; - isGood = !p.Data.IsImpostor; - } - else if (p.Data.IsImpostor) { // Just Impostor - name = "Impostor"; - color = Palette.ImpostorRed; - introDescription = ""; - shortDescription = "Sabotage and kill everyone"; - isGood = false; - } - else { // Just Crewmate - name = "Crewmate"; - color = Color.white; - introDescription = ""; - shortDescription = "Find the Impostors"; + infos.Add(new RoleInfo("Jester", + Jester.color, + "Get voted out", + "Get voted out")); + } + if (Mayor.mayor != null && p == Mayor.mayor) { + infos.Add(new RoleInfo("Mayor", + Mayor.color, + "Your vote counts twice", + "Your vote counts twice")); + } + if (Engineer.engineer != null && p == Engineer.engineer) { + infos.Add(new RoleInfo("Engineer", + Engineer.color, + "Maintain important systems on the ship", + "Repair the ship")); + } + if (Sheriff.sheriff != null && p == Sheriff.sheriff) { + infos.Add(new RoleInfo("Sheriff", + Sheriff.color, + "Shoot the [FF1919FF]Impostors", + "Shoot the Impostors")); + } + if (Lighter.lighter != null && p == Lighter.lighter) { + infos.Add(new RoleInfo("Lighter", + Lighter.color, + "Your light never goes out", + "Your light never goes out")); + } + if (Godfather.godfather != null && p == Godfather.godfather) { + infos.Add(new RoleInfo("Godfather", + Godfather.color, + "Kill all Crewmates", + "Kill all Crewmates")); + ; + } + if (Mafioso.mafioso != null && p == Mafioso.mafioso) { + infos.Add(new RoleInfo("Mafioso", + Mafioso.color, + "Work with the [FF1919FF]Mafia[] to kill the Crewmates", + "Kill all Crewmates")); + } + if (Janitor.janitor != null && p == Janitor.janitor) { + infos.Add(new RoleInfo("Janitor", + Janitor.color, + "Work with the [FF1919FF]Mafia[] by hiding dead bodies", + "Hide dead bodies")); + } + if (Morphling.morphling != null && p == Morphling.morphling) { + infos.Add(new RoleInfo("Morphling", + Morphling.color, + "Change your look to not get caught", + "Change your look")); + } + if (Camouflager.camouflager != null && p == Camouflager.camouflager) { + infos.Add(new RoleInfo("Camouflager", + Camouflager.color, + "Camouflage and kill the Crewmates", + "Hide among others")); + } + if (Vampire.vampire != null && p == Vampire.vampire) { + infos.Add(new RoleInfo("Vampire", + Vampire.color, + "Kill the Crewmates with your bites", + "Bite your enemies")); + } + if (Eraser.eraser != null && p == Eraser.eraser) { + infos.Add(new RoleInfo("Eraser", + Eraser.color, + "Kill the Crewmates and erase their roles", + "Erase the roles of your enemies")); + } + if (Detective.detective != null && p == Detective.detective) { + infos.Add(new RoleInfo("Detective", + Detective.color, + "Find the [FF1919FF]Impostors[] by examining footprints", + "Examine footprints")); + } + if (TimeMaster.timeMaster != null && p == TimeMaster.timeMaster) { + infos.Add(new RoleInfo("Time Master", + TimeMaster.color, + "Save yourself with your time shield", + "Use your time shield")); + } + if (Medic.medic != null && p == Medic.medic) { + infos.Add(new RoleInfo("Medic", + Medic.color, + "Protect someone with your shield", + "Protect other players")); + } + if (Shifter.shifter != null && p == Shifter.shifter) { + infos.Add(new RoleInfo("Shifter", + Shifter.color, + "Shift your role", + "Shift your role")); + } + if (Swapper.swapper != null && p == Swapper.swapper) { + infos.Add(new RoleInfo("Swapper", + Swapper.color, + "Swap votes to exile the [FF1919FF]Impostors", + "Swap votes")); + } + if (Seer.seer != null && p == Seer.seer) { + infos.Add(new RoleInfo("Seer", + Seer.color, + "You will see players die", + "You will see players die")); + } + if (Hacker.hacker != null && p == Hacker.hacker) { + infos.Add(new RoleInfo("Hacker", + Hacker.color, + "Hacker to find the [FF1919FF]Impostors", + "Hacker to find the Impostors")); + } + if (Child.child != null && p == Child.child) { + infos.Add(new RoleInfo(p.IDOFAMCIJKE.CIDDOFDJHJH ? "Bad Child" : "Good Child", + p.IDOFAMCIJKE.CIDDOFDJHJH ? Palette.LDCHDOFJPGH : Child.color, + "No one will harm you until you grow up", + "No one will harm you")); + } + if (BountyHunter.bountyHunter != null && p == BountyHunter.bountyHunter) { + infos.Add(new RoleInfo("Bounty Hunter", + BountyHunter.color, + "Hunt your bounty down", + "Hunt your bounty")); + ; + } + if (Tracker.tracker != null && p == Tracker.tracker) { + infos.Add(new RoleInfo("Tracker", + Tracker.color, + "Track the [FF1919FF]Impostors[] down", + "Track the Impostors down")); + } + if (Snitch.snitch != null && p == Snitch.snitch) { + infos.Add(new RoleInfo("Snitch", + Snitch.color, + "Finish your tasks to find the [FF1919FF]Impostors[]", + "Finish your tasks")); + } + if (Jackal.jackal != null && p == Jackal.jackal) { + infos.Add(new RoleInfo("Jackal", + Jackal.color, + "Kill all Crewmates and [FF1919FF]Impostors[FFFFFFFF] to win", + "Kill everyone")); + } + if (Sidekick.sidekick != null && p == Sidekick.sidekick) { + infos.Add(new RoleInfo("Sidekick", + Sidekick.color, + "", + "Help your Jackal to kill everyone")); + } + if ((Lovers.lover1 != null && p == Lovers.lover1) || (Lovers.lover2 != null && p == Lovers.lover2)) { + infos.Add(new RoleInfo(p.IDOFAMCIJKE.CIDDOFDJHJH ? "ImpLover" : "Lover", + p.IDOFAMCIJKE.CIDDOFDJHJH ? Palette.LDCHDOFJPGH : Lovers.color, + "You are in [FC03BEFF]Love[]", + "You are in love")); + } + + if (infos.Count == 0 && p.IDOFAMCIJKE.CIDDOFDJHJH) { // Just Impostor + infos.Add(new RoleInfo("Impostor", + Palette.LDCHDOFJPGH, + "", + "Sabotage and kill everyone")); + } else if (infos.Count == 0) { // Just Crewmate + infos.Add(new RoleInfo("Crewmate", + Color.white, + "", + "Find the Impostors")); } - return new RoleInfo( - color, - name, - introDescription, - shortDescription, - isGood - ); + return infos; } } } \ No newline at end of file diff --git a/Source Code/ShipStatusPatch.cs b/Source Code/ShipStatusPatch.cs index d5db201..2bca639 100644 --- a/Source Code/ShipStatusPatch.cs +++ b/Source Code/ShipStatusPatch.cs @@ -1,6 +1,11 @@ using HarmonyLib; using static TheOtherRoles.TheOtherRoles; +using UnityEngine; + +using SystemTypes = LGBKLKNAINN; +using SwitchSystem = FNEHFOPHPJO; +using ISystemType = CBFMKGACLNE; namespace TheOtherRoles { @@ -9,10 +14,23 @@ namespace TheOtherRoles { [HarmonyPostfix] [HarmonyPatch(typeof(ShipStatus), nameof(ShipStatus.CalculateLightRadius))] - public static void Postfix1(ref float __result, ShipStatus __instance, [HarmonyArgument(0)] GameData.PlayerInfo PlayerData) { - if (Lighter.lighter != null && Lighter.lighter.PlayerId == PlayerData.PlayerId) { - __result = __instance.MaxLightRadius * Lighter.lighterVision; - } + public static bool Prefix(ref float __result, ShipStatus __instance, [HarmonyArgument(0)] GameData.OFKOJOKOOAK player) { + ISystemType systemType = __instance.Systems.ContainsKey(SystemTypes.Electrical) ? __instance.Systems[SystemTypes.Electrical] : null; + if (systemType == null) return true; + SwitchSystem switchSystem = systemType.TryCast(); + if (switchSystem == null) return true; + + float num = (float)switchSystem.OBNIGODIBIO / 255f; + + if (player == null || player.FGNJJFABIHJ) + __result = __instance.MaxLightRadius; + else if (player.CIDDOFDJHJH) + __result = __instance.MaxLightRadius * PlayerControl.GameOptions.AFGNADFLBDB; + else if (Lighter.lighter != null && Lighter.lighter.PlayerId == player.GMBAIPNOKLP && Lighter.lighterTimer > 0f) + __result = Mathf.Lerp(__instance.MaxLightRadius * Lighter.lighterModeLightsOffVision, __instance.MaxLightRadius * Lighter.lighterModeLightsOnVision, num); + else + __result = Mathf.Lerp(__instance.MinLightRadius, __instance.MaxLightRadius, num) * PlayerControl.GameOptions.OJCJDCMDKKC; + return false; } [HarmonyPostfix] diff --git a/Source Code/TheOtherRoles.cs b/Source Code/TheOtherRoles.cs index 13f56d3..801de9c 100644 --- a/Source Code/TheOtherRoles.cs +++ b/Source Code/TheOtherRoles.cs @@ -5,14 +5,13 @@ using BepInEx.Configuration; using BepInEx.IL2CPP; using HarmonyLib; using Hazel; -using Reactor; using System; using System.Collections.Generic; using System.Collections; using System.IO; using UnityEngine; -using Reactor.Unstrip; -using Reactor.Extensions; + +using Palette = GLNPIJPGGNJ; namespace TheOtherRoles { @@ -39,7 +38,7 @@ namespace TheOtherRoles Seer.clearAndReload(); Morphling.clearAndReload(); Camouflager.clearAndReload(); - Spy.clearAndReload(); + Hacker.clearAndReload(); Child.clearAndReload(); BountyHunter.clearAndReload(); Tracker.clearAndReload(); @@ -47,6 +46,7 @@ namespace TheOtherRoles Snitch.clearAndReload(); Jackal.clearAndReload(); Sidekick.clearAndReload(); + Eraser.clearAndReload(); } public static class Jester { @@ -75,7 +75,7 @@ namespace TheOtherRoles public static Sprite getButtonSprite() { if (buttonSprite) return buttonSprite; - buttonSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.RepairButton.png", 100f); + buttonSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.RepairButton.png", 115f); return buttonSprite; } @@ -87,7 +87,7 @@ namespace TheOtherRoles public static class Godfather { public static PlayerControl godfather; - public static Color color = Palette.ImpostorRed; + public static Color color = Palette.LDCHDOFJPGH; public static void clearAndReload() { godfather = null; @@ -96,7 +96,7 @@ namespace TheOtherRoles public static class Mafioso { public static PlayerControl mafioso; - public static Color color = Palette.ImpostorRed; + public static Color color = Palette.LDCHDOFJPGH; public static void clearAndReload() { mafioso = null; @@ -106,20 +106,20 @@ namespace TheOtherRoles public static class Janitor { public static PlayerControl janitor; - public static Color color = Palette.ImpostorRed; + public static Color color = Palette.LDCHDOFJPGH; public static float cooldown = float.MaxValue; private static Sprite buttonSprite; public static Sprite getButtonSprite() { if (buttonSprite) return buttonSprite; - buttonSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.CleanButton.png", 100f); + buttonSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.CleanButton.png", 115f); return buttonSprite; } public static void clearAndReload() { janitor = null; - cooldown = TheOtherRolesPlugin.janitorCooldown.GetValue(); + cooldown = CustomOptionHolder.janitorCooldown.getFloat(); } } @@ -135,8 +135,8 @@ namespace TheOtherRoles public static void clearAndReload() { sheriff = null; currentTarget = null; - cooldown = TheOtherRolesPlugin.sheriffCooldown.GetValue(); - jesterCanDieToSheriff = TheOtherRolesPlugin.jesterCanDieToSheriff.GetValue(); + cooldown = CustomOptionHolder.sheriffCooldown.getFloat(); + jesterCanDieToSheriff = CustomOptionHolder.jesterCanDieToSheriff.getBool(); } } @@ -144,11 +144,28 @@ namespace TheOtherRoles public static PlayerControl lighter; public static Color color = new Color(250f / 255f, 204f / 255f, 37f / 255f, 1); - public static float lighterVision = 2f; + public static float lighterModeLightsOnVision = 2f; + public static float lighterModeLightsOffVision = 0.75f; + + public static float cooldown = float.MaxValue; + public static float duration = 5f; + + public static float lighterTimer = 0f; + + private static Sprite buttonSprite; + public static Sprite getButtonSprite() { + if (buttonSprite) return buttonSprite; + buttonSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.LighterButton.png", 115f); + return buttonSprite; + } public static void clearAndReload() { lighter = null; - lighterVision = TheOtherRolesPlugin.lighterVision.GetValue(); + lighterTimer = 0f; + cooldown = CustomOptionHolder.lighterCooldown.getFloat(); + duration = CustomOptionHolder.lighterDuration.getFloat(); + lighterModeLightsOnVision = CustomOptionHolder.lighterModeLightsOnVision.getFloat(); + lighterModeLightsOffVision = CustomOptionHolder.lighterModeLightsOffVision.getFloat(); } } @@ -159,14 +176,18 @@ namespace TheOtherRoles public static float footprintIntervall = 1f; public static float footprintDuration = 1f; public static bool anonymousFootprints = false; + public static float reportNameDuration = 0f; + public static float reportColorDuration = 20f; public static float timer = 1f; public static void clearAndReload() { detective = null; - anonymousFootprints = TheOtherRolesPlugin.detectiveAnonymousFootprints.GetValue(); - footprintIntervall = TheOtherRolesPlugin.detectiveFootprintIntervall.GetValue(); - footprintDuration = TheOtherRolesPlugin.detectiveFootprintDuration.GetValue(); + anonymousFootprints = CustomOptionHolder.detectiveAnonymousFootprints.getBool(); + footprintIntervall = CustomOptionHolder.detectiveFootprintIntervall.getFloat(); + footprintDuration = CustomOptionHolder.detectiveFootprintDuration.getFloat(); + reportNameDuration = CustomOptionHolder.detectiveReportNameDuration.getFloat(); + reportColorDuration = CustomOptionHolder.detectiveReportColorDuration.getFloat(); timer = footprintIntervall; } } @@ -178,23 +199,25 @@ namespace TheOtherRoles public static bool reviveDuringRewind = false; public static float rewindTime = 3f; + public static float shieldDuration = 3f; // Constant public static float cooldown = float.MaxValue; + public static bool shieldActive = false; public static bool isRewinding = false; private static Sprite buttonSprite; public static Sprite getButtonSprite() { if (buttonSprite) return buttonSprite; - buttonSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.RewindButton.png", 100f); + buttonSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.TimeShieldButton.png", 115f); return buttonSprite; } public static void clearAndReload() { timeMaster = null; isRewinding = false; - reviveDuringRewind = TheOtherRolesPlugin.timeMasterReviveDuringRewind.GetValue(); - rewindTime = TheOtherRolesPlugin.timeMasterRewindTime.GetValue(); - cooldown = TheOtherRolesPlugin.timeMasterCooldown.GetValue(); + shieldActive = false; + rewindTime = CustomOptionHolder.timeMasterRewindTime.getFloat(); + cooldown = CustomOptionHolder.timeMasterCooldown.getFloat(); } } @@ -204,8 +227,6 @@ namespace TheOtherRoles public static Color color = new Color(0f / 255f, 80f / 255f, 105f / 255f, 1); public static bool usedShield; - public static float reportNameDuration = 10f; - public static float reportColorDuration = 20f; public static int showShielded = 0; public static bool showAttemptToShielded = false; @@ -215,43 +236,40 @@ namespace TheOtherRoles private static Sprite buttonSprite; public static Sprite getButtonSprite() { if (buttonSprite) return buttonSprite; - buttonSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.ShieldButton.png", 100f); + buttonSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.ShieldButton.png", 115f); return buttonSprite; } public static void clearAndReload() { medic = null; - if (shielded?.myRend?.material != null) shielded.myRend.material.SetFloat("_Outline", 0f); + if (shielded?.LNMJKMLHMIM?.material != null) shielded.LNMJKMLHMIM.material.SetFloat("_Outline", 0f); shielded = null; currentTarget = null; usedShield = false; shieldedColor = new Color(0f / 255f, 221f / 255f, 255f / 255f, 1); - reportNameDuration = TheOtherRolesPlugin.medicReportNameDuration.GetValue(); - reportColorDuration = TheOtherRolesPlugin.medicReportColorDuration.GetValue(); - showShielded = TheOtherRolesPlugin.medicShowShielded.GetValue(); - showAttemptToShielded = TheOtherRolesPlugin.medicShowAttemptToShielded.GetValue(); + showShielded = CustomOptionHolder.medicShowShielded.getSelection(); + showAttemptToShielded = CustomOptionHolder.medicShowAttemptToShielded.getBool(); } } public static class Shifter { public static PlayerControl shifter; public static Color color = new Color(90f / 255f, 90f / 255f, 90f / 255f, 1); - - public static float cooldown = float.MaxValue; + public static PlayerControl futureShift; public static PlayerControl currentTarget; private static Sprite buttonSprite; public static Sprite getButtonSprite() { if (buttonSprite) return buttonSprite; - buttonSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.ShiftButton.png", 100f); + buttonSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.ShiftButton.png", 115f); return buttonSprite; } public static void clearAndReload() { shifter = null; currentTarget = null; - cooldown = TheOtherRolesPlugin.shifterCooldown.GetValue(); + futureShift = null; } } @@ -286,53 +304,47 @@ namespace TheOtherRoles public static bool notAckedExiledIsLover = false; public static bool existingAndAlive() { - return lover1 != null && lover2 != null && !lover1.Data.IsDead && !lover2.Data.IsDead && !lover1.Data.Disconnected && !lover2.Data.Disconnected && !notAckedExiledIsLover; // ADD NOT ACKED IS LOVER + return lover1 != null && lover2 != null && !lover1.IDOFAMCIJKE.FGNJJFABIHJ && !lover2.IDOFAMCIJKE.FGNJJFABIHJ && !lover1.IDOFAMCIJKE.GBPMEHJFECK && !lover2.IDOFAMCIJKE.GBPMEHJFECK && !notAckedExiledIsLover; // ADD NOT ACKED IS LOVER } public static bool existingWithImpLover() { - return lover1 != null && lover2 != null && !lover1.Data.Disconnected && !lover2.Data.Disconnected && (lover1.Data.IsImpostor || lover2.Data.IsImpostor); + return lover1 != null && lover2 != null && !lover1.IDOFAMCIJKE.GBPMEHJFECK && !lover2.IDOFAMCIJKE.GBPMEHJFECK && (lover1.IDOFAMCIJKE.CIDDOFDJHJH || lover2.IDOFAMCIJKE.CIDDOFDJHJH); } public static void clearAndReload() { lover1 = null; lover2 = null; notAckedExiledIsLover = false; - bothDie = TheOtherRolesPlugin.loversBothDie.GetValue(); + bothDie = CustomOptionHolder.loversBothDie.getBool(); } } public static class Seer { public static PlayerControl seer; public static Color color = new Color(60f / 255f, 181f / 255f, 100f / 255f, 1); - public static Dictionary revealedPlayers = new Dictionary(); + public static List deadBodyPositions = new List(); - public static float cooldown = float.MaxValue; - public static int kindOfInfo = 0; - public static int playersWithNotification = 0; - public static float chanceOfSeeingRight = 100; + public static float soulDuration = 15f; + public static int mode = 0; - public static PlayerControl currentTarget; - - private static Sprite buttonSprite; - public static Sprite getButtonSprite() { - if (buttonSprite) return buttonSprite; - buttonSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.SeerButton.png", 100f); - return buttonSprite; + private static Sprite soulSprite; + public static Sprite getSoulSprite() { + if (soulSprite) return soulSprite; + soulSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.Soul.png", 500f); + return soulSprite; } public static void clearAndReload() { seer = null; - revealedPlayers = new Dictionary(); - cooldown = TheOtherRolesPlugin.seerCooldown.GetValue(); - kindOfInfo = TheOtherRolesPlugin.seerKindOfInfo.GetValue(); - playersWithNotification = TheOtherRolesPlugin.seerPlayersWithNotification.GetValue(); - chanceOfSeeingRight = TheOtherRolesPlugin.seerChanceOfSeeingRight.GetValue(); + deadBodyPositions = new List(); + soulDuration = CustomOptionHolder.seerSoulDuration.getFloat(); + mode = CustomOptionHolder.medicShowShielded.getSelection(); } } public static class Morphling { public static PlayerControl morphling; - public static Color color = Palette.ImpostorRed; + public static Color color = Palette.LDCHDOFJPGH; private static Sprite sampleSprite; private static Sprite morphSprite; @@ -347,12 +359,13 @@ namespace TheOtherRoles morphTarget = null; morphTimer = 0f; if (morphling == null) return; - morphling.SetName(morphling.Data.PlayerName); - morphling.SetHat(morphling.Data.HatId, (int)morphling.Data.ColorId); - Helpers.setSkinWithAnim(morphling.MyPhysics, morphling.Data.SkinId); - morphling.SetPet(morphling.Data.PetId); - morphling.CurrentPet.Visible = morphling.Visible; - morphling.SetColor(morphling.Data.ColorId); + morphling.SetName(morphling.IDOFAMCIJKE.HGGCLJHCDBM); + morphling.SetHat(morphling.IDOFAMCIJKE.MFIOGLKPMGD, (int)morphling.IDOFAMCIJKE.JFHFMIKFHGG); + Helpers.setSkinWithAnim(morphling.MyPhysics, morphling.IDOFAMCIJKE.LFDAHOFPIAM); + morphling.SetPet(morphling.IDOFAMCIJKE.GKFOHNJHFOE); + morphling.CurrentPet.FHBHBMIJFID = morphling.FHBHBMIJFID; + morphling.SetColor(morphling.IDOFAMCIJKE.JFHFMIKFHGG); + morphling.LNMJKMLHMIM.material.SetFloat("_Outline", 0f); } public static void clearAndReload() { @@ -362,25 +375,25 @@ namespace TheOtherRoles sampledTarget = null; morphTarget = null; morphTimer = 0f; - cooldown = TheOtherRolesPlugin.morphlingCooldown.GetValue(); + cooldown = CustomOptionHolder.morphlingCooldown.getFloat(); } public static Sprite getSampleSprite() { if (sampleSprite) return sampleSprite; - sampleSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.SampleButton.png", 100f); + sampleSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.SampleButton.png", 115f); return sampleSprite; } public static Sprite getMorphSprite() { if (morphSprite) return morphSprite; - morphSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.MorphButton.png", 100f); + morphSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.MorphButton.png", 115f); return morphSprite; } } public static class Camouflager { public static PlayerControl camouflager; - public static Color color = Palette.ImpostorRed; + public static Color color = Palette.LDCHDOFJPGH; public static float cooldown = float.MaxValue; public static float camouflageTimer = 0f; @@ -388,7 +401,7 @@ namespace TheOtherRoles private static Sprite buttonSprite; public static Sprite getButtonSprite() { if (buttonSprite) return buttonSprite; - buttonSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.CamoButton.png", 100f); + buttonSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.CamoButton.png", 115f); return buttonSprite; } @@ -397,12 +410,12 @@ namespace TheOtherRoles foreach (PlayerControl p in PlayerControl.AllPlayerControls) { if (p == null) continue; if (Morphling.morphling == null || Morphling.morphling != p) { - p.SetName(p.Data.PlayerName); - p.SetHat(p.Data.HatId, (int)p.Data.ColorId); - Helpers.setSkinWithAnim(p.MyPhysics, p.Data.SkinId); - p.SetPet(p.Data.PetId); - p.CurrentPet.Visible = p.Visible; - p.SetColor(p.Data.ColorId); + p.SetName(p.IDOFAMCIJKE.HGGCLJHCDBM); + p.SetHat(p.IDOFAMCIJKE.MFIOGLKPMGD, (int)p.IDOFAMCIJKE.JFHFMIKFHGG); + Helpers.setSkinWithAnim(p.MyPhysics, p.IDOFAMCIJKE.LFDAHOFPIAM); + p.SetPet(p.IDOFAMCIJKE.GKFOHNJHFOE); + p.CurrentPet.FHBHBMIJFID = p.FHBHBMIJFID; + p.SetColor(p.IDOFAMCIJKE.JFHFMIKFHGG); } } } @@ -411,19 +424,20 @@ namespace TheOtherRoles resetCamouflage(); camouflager = null; camouflageTimer = 0f; - cooldown = TheOtherRolesPlugin.camouflagerCooldown.GetValue(); + cooldown = CustomOptionHolder.camouflagerCooldown.getFloat(); } } - public static class Spy { - public static PlayerControl spy; + public static class Hacker { + public static PlayerControl hacker; private static Sprite adminTableIcon; public static Color color = new Color(252f / 255f, 90f / 255f, 30f / 255f, 1); public static float cooldown = float.MaxValue; public static float duration = 10f; + public static bool onlyColorType = false; - public static float spyTimer = 0f; + public static float hackerTimer = 0f; public static Sprite getAdminTableIconSprite() { if (adminTableIcon) return adminTableIcon; @@ -434,15 +448,16 @@ namespace TheOtherRoles private static Sprite buttonSprite; public static Sprite getButtonSprite() { if (buttonSprite) return buttonSprite; - buttonSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.SpyButton.png", 100f); + buttonSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.HackerButton.png", 115f); return buttonSprite; } public static void clearAndReload() { - spy = null; - spyTimer = 0f; - cooldown = TheOtherRolesPlugin.spyCooldown.GetValue(); - duration = TheOtherRolesPlugin.spySpyingDuration.GetValue(); + hacker = null; + hackerTimer = 0f; + cooldown = CustomOptionHolder.hackerCooldown.getFloat(); + duration = CustomOptionHolder.hackerHackeringDuration.getFloat(); + onlyColorType = CustomOptionHolder.hackerOnlyColorType.getBool(); } } @@ -452,10 +467,12 @@ namespace TheOtherRoles public static float growingUpDuration = float.MaxValue; public static DateTime timeOfGrowthStart = DateTime.UtcNow; + public static bool triggerChildLose = false; public static void clearAndReload() { child = null; - growingUpDuration = TheOtherRolesPlugin.childGrowingUpDuration.GetValue(); + triggerChildLose = false; + growingUpDuration = CustomOptionHolder.childGrowingUpDuration.getFloat(); timeOfGrowthStart = DateTime.UtcNow; } @@ -481,7 +498,7 @@ namespace TheOtherRoles public static void clearAndReload() { bountyHunter = null; target = null; - // notifyBounty = TheOtherRolesPlugin.bountyHunterNotifyBounty.GetValue(); + // notifyBounty = CustomOptionHolder.bountyHunterNotifyBounty.getBool(); } } @@ -500,7 +517,7 @@ namespace TheOtherRoles private static Sprite buttonSprite; public static Sprite getButtonSprite() { if (buttonSprite) return buttonSprite; - buttonSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.TrackerButton.png", 100f); + buttonSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.TrackerButton.png", 115f); return buttonSprite; } @@ -510,7 +527,7 @@ namespace TheOtherRoles tracked = null; usedTracker = false; timeUntilUpdate = 0f; - updateIntervall = TheOtherRolesPlugin.trackerUpdateIntervall.GetValue(); + updateIntervall = CustomOptionHolder.trackerUpdateIntervall.getFloat(); if (arrow?.arrow != null) UnityEngine.Object.Destroy(arrow.arrow); arrow = new Arrow(Color.blue); if (arrow.arrow != null) arrow.arrow.SetActive(false); @@ -519,7 +536,7 @@ namespace TheOtherRoles public static class Vampire { public static PlayerControl vampire; - public static Color color = Palette.ImpostorRed; + public static Color color = Palette.LDCHDOFJPGH; public static float delay = 10f; public static float cooldown = float.MaxValue; @@ -528,40 +545,33 @@ namespace TheOtherRoles public static bool garlicsActive = true; public static PlayerControl currentTarget; - public static PlayerControl bitten; + public static PlayerControl bitten; public static bool targetNearGarlic = false; private static Sprite buttonSprite; public static Sprite getButtonSprite() { if (buttonSprite) return buttonSprite; - buttonSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.VampireButton.png", 100f); + buttonSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.VampireButton.png", 115f); return buttonSprite; } private static Sprite garlicButtonSprite; public static Sprite getGarlicButtonSprite() { if (garlicButtonSprite) return garlicButtonSprite; - garlicButtonSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.GarlicButton.png", 100f); + garlicButtonSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.GarlicButton.png", 115f); return garlicButtonSprite; } - public static IEnumerator killWithDelay() { - yield return new WaitForSeconds(delay); - MessageWriter killWriter = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.VampireTryKill, Hazel.SendOption.Reliable, -1); - AmongUsClient.Instance.FinishRpcImmediately(killWriter); - RPCProcedure.vampireTryKill(); - } - public static void clearAndReload() { vampire = null; bitten = null; targetNearGarlic = false; localPlacedGarlic = false; currentTarget = null; - garlicsActive = TheOtherRolesPlugin.vampireSpawnRate.GetValue() > 0; - delay = TheOtherRolesPlugin.vampireKillDelay.GetValue(); - cooldown = TheOtherRolesPlugin.vampireCooldown.GetValue(); - canKillNearGarlics = TheOtherRolesPlugin.vampireCanKillNearGarlics.GetValue(); + garlicsActive = CustomOptionHolder.vampireSpawnRate.getSelection() > 0; + delay = CustomOptionHolder.vampireKillDelay.getFloat(); + cooldown = CustomOptionHolder.vampireCooldown.getFloat(); + canKillNearGarlics = CustomOptionHolder.vampireCanKillNearGarlics.getBool(); } } @@ -579,7 +589,7 @@ namespace TheOtherRoles UnityEngine.Object.Destroy(arrow.arrow); } localArrows = new List(); - taskCountForImpostors = Mathf.RoundToInt(TheOtherRolesPlugin.snitchLeftTasksForImpostors.GetValue()); + taskCountForImpostors = Mathf.RoundToInt(CustomOptionHolder.snitchLeftTasksForImpostors.getFloat()); snitch = null; } } @@ -602,7 +612,7 @@ namespace TheOtherRoles public static Sprite getSidekickButtonSprite() { if (buttonSprite) return buttonSprite; - buttonSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.SidekickButton.png", 100f); + buttonSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.SidekickButton.png", 115f); return buttonSprite; } @@ -611,20 +621,20 @@ namespace TheOtherRoles jackal = null; currentTarget = null; fakeSidekick = null; - cooldown = TheOtherRolesPlugin.jackalKillCooldown.GetValue(); - createSidekickCooldown = TheOtherRolesPlugin.jackalCreateSidekickCooldown.GetValue(); + cooldown = CustomOptionHolder.jackalKillCooldown.getFloat(); + createSidekickCooldown = CustomOptionHolder.jackalCreateSidekickCooldown.getFloat(); } public static void clearAndReload() { jackal = null; currentTarget = null; fakeSidekick = null; - cooldown = TheOtherRolesPlugin.jackalKillCooldown.GetValue(); - createSidekickCooldown = TheOtherRolesPlugin.jackalCreateSidekickCooldown.GetValue(); - canUseVents = TheOtherRolesPlugin.jackalCanUseVents.GetValue(); - canCreateSidekick = TheOtherRolesPlugin.jackalCanCreateSidekick.GetValue(); - jackalPromotedFromSidekickCanCreateSidekick = TheOtherRolesPlugin.jackalPromotedFromSidekickCanCreateSidekick.GetValue(); - canCreateSidekickFromImpostor = TheOtherRolesPlugin.jackalCanCreateSidekickFromImpostor.GetValue(); + cooldown = CustomOptionHolder.jackalKillCooldown.getFloat(); + createSidekickCooldown = CustomOptionHolder.jackalCreateSidekickCooldown.getFloat(); + canUseVents = CustomOptionHolder.jackalCanUseVents.getBool(); + canCreateSidekick = CustomOptionHolder.jackalCanCreateSidekick.getBool(); + jackalPromotedFromSidekickCanCreateSidekick = CustomOptionHolder.jackalPromotedFromSidekickCanCreateSidekick.getBool(); + canCreateSidekickFromImpostor = CustomOptionHolder.jackalCanCreateSidekickFromImpostor.getBool(); formerJackals.Clear(); } @@ -644,12 +654,33 @@ namespace TheOtherRoles public static void clearAndReload() { sidekick = null; currentTarget = null; - cooldown = TheOtherRolesPlugin.jackalKillCooldown.GetValue(); - canUseVents = TheOtherRolesPlugin.sidekickCanUseVents.GetValue(); - canKill = TheOtherRolesPlugin.sidekickCanKill.GetValue(); - promotesToJackal = TheOtherRolesPlugin.sidekickPromotesToJackal.GetValue(); + cooldown = CustomOptionHolder.jackalKillCooldown.getFloat(); + canUseVents = CustomOptionHolder.sidekickCanUseVents.getBool(); + canKill = CustomOptionHolder.sidekickCanKill.getBool(); + promotesToJackal = CustomOptionHolder.sidekickPromotesToJackal.getBool(); } - } + public static class Eraser { + public static PlayerControl eraser; + public static Color color = Palette.LDCHDOFJPGH; + + public static List futureErased = new List(); + public static PlayerControl currentTarget; + public static float cooldown = float.MaxValue; + + private static Sprite buttonSprite; + public static Sprite getButtonSprite() { + if (buttonSprite) return buttonSprite; + buttonSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.EraserButton.png", 115f); + return buttonSprite; + } + + public static void clearAndReload() { + eraser = null; + futureErased = new List(); + currentTarget = null; + cooldown = CustomOptionHolder.eraserCooldown.getFloat(); + } + } } \ No newline at end of file diff --git a/Source Code/TheOtherRoles.csproj b/Source Code/TheOtherRoles.csproj deleted file mode 100644 index 983010a..0000000 --- a/Source Code/TheOtherRoles.csproj +++ /dev/null @@ -1,60 +0,0 @@ - - - netstandard2.1 - 1.0.0 - NuclearPowered/Mappings:0.2.0 - - TheOtherRoles - Eisbison - - - - 2021.3.5s - $(DefineConstants);STEAM - - - - 2021.3.5i - $(DefineConstants);ITCH - - - - - - - - - - - $(AmongUs)\BepInEx\plugins\Essentials-$(GameVersion).dll - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Source Code/UpdatePatch.cs b/Source Code/UpdatePatch.cs index 0dfc018..3cdcd80 100644 --- a/Source Code/UpdatePatch.cs +++ b/Source Code/UpdatePatch.cs @@ -4,10 +4,11 @@ using System.IO; using System.Net.Http; using UnityEngine; using static TheOtherRoles.TheOtherRoles; -using Reactor.Extensions; using System.Collections.Generic; using System.Linq; +using Palette = GLNPIJPGGNJ; + namespace TheOtherRoles { [HarmonyPatch(typeof(HudManager), nameof(HudManager.Update))] @@ -17,36 +18,36 @@ namespace TheOtherRoles Dictionary playersById = Helpers.allPlayersById(); foreach (PlayerControl player in PlayerControl.AllPlayerControls) { - player.nameText.Text = player.Data.PlayerName; - if (PlayerControl.LocalPlayer.Data.IsImpostor && player.Data.IsImpostor) { - player.nameText.Color = Palette.ImpostorRed; + player.nameText.Text = player.IDOFAMCIJKE.HGGCLJHCDBM; + if (PlayerControl.LocalPlayer.IDOFAMCIJKE.CIDDOFDJHJH && player.IDOFAMCIJKE.CIDDOFDJHJH) { + player.nameText.Color = Palette.LDCHDOFJPGH; } else { player.nameText.Color = Color.white; } } if (MeetingHud.Instance != null) { - foreach (PlayerVoteArea player in MeetingHud.Instance.playerStates) { - PlayerControl playerControl = playersById.ContainsKey((byte)player.TargetPlayerId) ? playersById[(byte)player.TargetPlayerId] : null; + foreach (PlayerVoteArea player in MeetingHud.Instance.DHCOPOOJCLN) { + PlayerControl playerControl = playersById.ContainsKey((byte)player.HMPHKKGPLAG) ? playersById[(byte)player.HMPHKKGPLAG] : null; if (playerControl != null) { - player.NameText.Text = playerControl.Data.PlayerName; - if (PlayerControl.LocalPlayer.Data.IsImpostor && playerControl.Data.IsImpostor) { - player.NameText.Color = Palette.ImpostorRed; + player.NameText.Text = playerControl.IDOFAMCIJKE.HGGCLJHCDBM; + if (PlayerControl.LocalPlayer.IDOFAMCIJKE.CIDDOFDJHJH && playerControl.IDOFAMCIJKE.CIDDOFDJHJH) { + player.NameText.Color = Palette.LDCHDOFJPGH; } else { player.NameText.Color = Color.white; } } } } - if (PlayerControl.LocalPlayer.Data.IsImpostor) { + if (PlayerControl.LocalPlayer.IDOFAMCIJKE.CIDDOFDJHJH) { List impostors = PlayerControl.AllPlayerControls.ToArray().ToList(); - impostors.RemoveAll(x => !x.Data.IsImpostor); + impostors.RemoveAll(x => !x.IDOFAMCIJKE.CIDDOFDJHJH); foreach (PlayerControl player in impostors) - player.nameText.Color = Palette.ImpostorRed; + player.nameText.Color = Palette.LDCHDOFJPGH; if (MeetingHud.Instance != null) - foreach (PlayerVoteArea player in MeetingHud.Instance.playerStates) { - PlayerControl playerControl = Helpers.playerById((byte)player.TargetPlayerId); - if (playerControl != null && playerControl.Data.IsImpostor) - player.NameText.Color = Palette.ImpostorRed; + foreach (PlayerVoteArea player in MeetingHud.Instance.DHCOPOOJCLN) { + PlayerControl playerControl = Helpers.playerById((byte)player.HMPHKKGPLAG); + if (playerControl != null && playerControl.IDOFAMCIJKE.CIDDOFDJHJH) + player.NameText.Color = Palette.LDCHDOFJPGH; } } @@ -55,8 +56,8 @@ namespace TheOtherRoles static void setPlayerNameColor(PlayerControl p, Color color) { p.nameText.Color = color; if (MeetingHud.Instance != null) - foreach (PlayerVoteArea player in MeetingHud.Instance.playerStates) - if (player.NameText != null && p.PlayerId == player.TargetPlayerId) + foreach (PlayerVoteArea player in MeetingHud.Instance.DHCOPOOJCLN) + if (player.NameText != null && p.PlayerId == player.HMPHKKGPLAG) player.NameText.Color = color; } @@ -87,8 +88,8 @@ namespace TheOtherRoles } else if (Seer.seer != null && Seer.seer == PlayerControl.LocalPlayer) setPlayerNameColor(Seer.seer, Seer.color); - else if (Spy.spy != null && Spy.spy == PlayerControl.LocalPlayer) - setPlayerNameColor(Spy.spy, Spy.color); + else if (Hacker.hacker != null && Hacker.hacker == PlayerControl.LocalPlayer) + setPlayerNameColor(Hacker.hacker, Hacker.color); else if (BountyHunter.bountyHunter != null && BountyHunter.target != null && BountyHunter.bountyHunter == PlayerControl.LocalPlayer) { setPlayerNameColor(BountyHunter.bountyHunter, BountyHunter.color); setPlayerNameColor(BountyHunter.target, BountyHunter.color); @@ -118,26 +119,26 @@ namespace TheOtherRoles } // Crewmate roles with no changes: Child - // Impostor roles with no changes: Morphling, Camouflager, Vampire, Godfather, Janitor and Mafioso + // Impostor roles with no changes: Morphling, Camouflager, Vampire, Godfather, Eraser, Janitor and Mafioso } static void setMafiaNameTags() { - if (PlayerControl.LocalPlayer != null && PlayerControl.LocalPlayer.Data.IsImpostor) { + if (PlayerControl.LocalPlayer != null && PlayerControl.LocalPlayer.IDOFAMCIJKE.CIDDOFDJHJH) { foreach (PlayerControl player in PlayerControl.AllPlayerControls) if (Godfather.godfather != null && Godfather.godfather == player) - player.nameText.Text = player.Data.PlayerName + " (G)"; + player.nameText.Text = player.IDOFAMCIJKE.HGGCLJHCDBM + " (G)"; else if (Mafioso.mafioso != null && Mafioso.mafioso == player) - player.nameText.Text = player.Data.PlayerName + " (M)"; + player.nameText.Text = player.IDOFAMCIJKE.HGGCLJHCDBM + " (M)"; else if (Janitor.janitor != null && Janitor.janitor == player) - player.nameText.Text = player.Data.PlayerName + " (J)"; + player.nameText.Text = player.IDOFAMCIJKE.HGGCLJHCDBM + " (J)"; if (MeetingHud.Instance != null) - foreach (PlayerVoteArea player in MeetingHud.Instance.playerStates) - if (Godfather.godfather != null && Godfather.godfather.PlayerId == player.TargetPlayerId) - player.NameText.Text = Godfather.godfather.Data.PlayerName + " (G)"; - else if (Mafioso.mafioso != null && Mafioso.mafioso.PlayerId == player.TargetPlayerId) - player.NameText.Text = Mafioso.mafioso.Data.PlayerName + " (M)"; - else if (Janitor.janitor != null && Janitor.janitor.PlayerId == player.TargetPlayerId) - player.NameText.Text = Janitor.janitor.Data.PlayerName + " (J)"; + foreach (PlayerVoteArea player in MeetingHud.Instance.DHCOPOOJCLN) + if (Godfather.godfather != null && Godfather.godfather.PlayerId == player.HMPHKKGPLAG) + player.NameText.Text = Godfather.godfather.IDOFAMCIJKE.HGGCLJHCDBM + " (G)"; + else if (Mafioso.mafioso != null && Mafioso.mafioso.PlayerId == player.HMPHKKGPLAG) + player.NameText.Text = Mafioso.mafioso.IDOFAMCIJKE.HGGCLJHCDBM + " (M)"; + else if (Janitor.janitor != null && Janitor.janitor.PlayerId == player.HMPHKKGPLAG) + player.NameText.Text = Janitor.janitor.IDOFAMCIJKE.HGGCLJHCDBM + " (J)"; } } @@ -146,23 +147,23 @@ namespace TheOtherRoles if(Medic.showShielded == 0) // Everyone { - Medic.shielded.myRend.material.SetFloat("_Outline", 1f); - Medic.shielded.myRend.material.SetColor("_OutlineColor", Medic.shieldedColor); + Medic.shielded.LNMJKMLHMIM.material.SetFloat("_Outline", 1f); + Medic.shielded.LNMJKMLHMIM.material.SetColor("_OutlineColor", Medic.shieldedColor); } else if (Medic.showShielded == 1 && PlayerControl.LocalPlayer == Medic.shielded) // Shielded + Medic { - Medic.shielded.myRend.material.SetFloat("_Outline", 1f); - Medic.shielded.myRend.material.SetColor("_OutlineColor", Medic.shieldedColor); + Medic.shielded.LNMJKMLHMIM.material.SetFloat("_Outline", 1f); + Medic.shielded.LNMJKMLHMIM.material.SetColor("_OutlineColor", Medic.shieldedColor); } else if(PlayerControl.LocalPlayer == Medic.medic) // Medic { - Medic.shielded.myRend.material.SetFloat("_Outline", 1f); - Medic.shielded.myRend.material.SetColor("_OutlineColor", Medic.shieldedColor); + Medic.shielded.LNMJKMLHMIM.material.SetFloat("_Outline", 1f); + Medic.shielded.LNMJKMLHMIM.material.SetColor("_OutlineColor", Medic.shieldedColor); } // Break shield - if (Medic.shielded.Data.IsDead || Medic.medic == null || Medic.medic.Data.IsDead) { - Medic.shielded.myRend.material.SetFloat("_Outline", 0f); + if (Medic.shielded.IDOFAMCIJKE.FGNJJFABIHJ || Medic.medic == null || Medic.medic.IDOFAMCIJKE.FGNJJFABIHJ) { + Medic.shielded.LNMJKMLHMIM.material.SetFloat("_Outline", 0f); Medic.shielded = null; } } @@ -170,7 +171,7 @@ namespace TheOtherRoles static void mafiosoDeactivateKillButtonIfNecessary(HudManager __instance) { if (Mafioso.mafioso == null || Mafioso.mafioso != PlayerControl.LocalPlayer) return; - if (!PlayerControl.LocalPlayer.Data.IsDead && __instance.UseButton.isActiveAndEnabled && Godfather.godfather != null && Godfather.godfather.Data.IsDead) { + if (!PlayerControl.LocalPlayer.IDOFAMCIJKE.FGNJJFABIHJ && __instance.UseButton.isActiveAndEnabled && Godfather.godfather != null && Godfather.godfather.IDOFAMCIJKE.FGNJJFABIHJ) { __instance.KillButton.gameObject.SetActive(true); __instance.KillButton.renderer.enabled = true; __instance.KillButton.isActive = true; @@ -192,42 +193,9 @@ namespace TheOtherRoles } } - static void seerUpdate() { - if (Seer.seer == null || Seer.seer != PlayerControl.LocalPlayer) return; - - // Update revealed players - foreach (KeyValuePair entry in Seer.revealedPlayers) { - PlayerControl target = entry.Key; - PlayerControl targetOrMistake = entry.Value; - - if (target == null || targetOrMistake == null) continue; - - // Update color and name regarding settings and given info - string result = target.Data.PlayerName; - RoleInfo si = RoleInfo.getRoleInfoForPlayer(targetOrMistake); - if (Seer.kindOfInfo == 0) - result = target.Data.PlayerName + " (" + si.name + ")"; - else if (Seer.kindOfInfo == 1) { - si.color = si.isGood ? new Color(250f / 255f, 217f / 255f, 52f / 255f, 1) : new Color (51f / 255f, 61f / 255f, 54f / 255f, 1); - } - - // Set color and name - target.nameText.Color = si.color; - target.nameText.Text = result; - if (MeetingHud.Instance != null) { - foreach (PlayerVoteArea player in MeetingHud.Instance.playerStates) { - if (target.PlayerId == player.TargetPlayerId) { - player.NameText.Text = result; - player.NameText.Color = si.color; - break; - } - } - } - } - } - - static void spyUpdate() { - Spy.spyTimer -= Time.deltaTime; + static void timerUpdate() { + Hacker.hackerTimer -= Time.deltaTime; + Lighter.lighterTimer -= Time.deltaTime; } static void camouflageAndMorphActions() { @@ -242,25 +210,26 @@ namespace TheOtherRoles // Set morphling morphed look if (Morphling.morphTimer > 0f && Camouflager.camouflageTimer <= 0f) { if (Morphling.morphling != null && Morphling.morphTarget != null) { - if (Seer.seer == null || Seer.seer != PlayerControl.LocalPlayer) - Morphling.morphling.nameText.Text = Morphling.morphTarget.Data.PlayerName; - Morphling.morphling.myRend.material.SetColor("_BackColor", Palette.ShadowColors[Morphling.morphTarget.Data.ColorId]); - Morphling.morphling.myRend.material.SetColor("_BodyColor", Palette.PlayerColors[Morphling.morphTarget.Data.ColorId]); - Morphling.morphling.HatRenderer.SetHat(Morphling.morphTarget.Data.HatId, Morphling.morphTarget.Data.ColorId); - Morphling.morphling.nameText.transform.localPosition = new Vector3(0f, (Morphling.morphTarget.Data.HatId == 0U) ? 0.7f : 1.05f, -0.5f); - - if (Morphling.morphling.MyPhysics.Skin.skin.ProdId != DestroyableSingleton.Instance.AllSkins[(int)Morphling.morphTarget.Data.SkinId].ProdId) { - Helpers.setSkinWithAnim(Morphling.morphling.MyPhysics, Morphling.morphTarget.Data.SkinId); + Morphling.morphling.nameText.Text = Morphling.morphTarget.IDOFAMCIJKE.HGGCLJHCDBM; + Morphling.morphling.LNMJKMLHMIM.material.SetColor("_BackColor", Palette.CHIIBPFJACF[Morphling.morphTarget.IDOFAMCIJKE.JFHFMIKFHGG]); + Morphling.morphling.LNMJKMLHMIM.material.SetColor("_BodyColor", Palette.CALCLMEEPGL[Morphling.morphTarget.IDOFAMCIJKE.JFHFMIKFHGG]); + Morphling.morphling.LNMJKMLHMIM.material.SetFloat("_Outline", Morphling.morphTarget.LNMJKMLHMIM.material.GetFloat("_Outline")); + Morphling.morphling.LNMJKMLHMIM.material.SetColor("_OutlineColor", Morphling.morphTarget.LNMJKMLHMIM.material.GetColor("_OutlineColor")); + Morphling.morphling.HatRenderer.SetHat(Morphling.morphTarget.IDOFAMCIJKE.MFIOGLKPMGD, Morphling.morphTarget.IDOFAMCIJKE.JFHFMIKFHGG); + Morphling.morphling.nameText.transform.localPosition = new Vector3(0f, (Morphling.morphTarget.IDOFAMCIJKE.MFIOGLKPMGD == 0U) ? 0.7f : 1.05f, -0.5f); + + if (Morphling.morphling.MyPhysics.Skin.skin.ProdId != DestroyableSingleton.CMJOLNCMAPD.AllSkins[(int)Morphling.morphTarget.IDOFAMCIJKE.LFDAHOFPIAM].ProdId) { + Helpers.setSkinWithAnim(Morphling.morphling.MyPhysics, Morphling.morphTarget.IDOFAMCIJKE.LFDAHOFPIAM); } - if (Morphling.morphling.CurrentPet == null || Morphling.morphling.CurrentPet.ProdId != DestroyableSingleton.Instance.AllPets[(int)Morphling.morphTarget.Data.PetId].ProdId) { + if (Morphling.morphling.CurrentPet == null || Morphling.morphling.CurrentPet.EKONGILOOPE != DestroyableSingleton.CMJOLNCMAPD.AllPets[(int)Morphling.morphTarget.IDOFAMCIJKE.GKFOHNJHFOE].EKONGILOOPE) { if (Morphling.morphling.CurrentPet) UnityEngine.Object.Destroy(Morphling.morphling.CurrentPet.gameObject); - Morphling.morphling.CurrentPet = UnityEngine.Object.Instantiate(DestroyableSingleton.Instance.AllPets[(int)Morphling.morphTarget.Data.PetId]); + Morphling.morphling.CurrentPet = UnityEngine.Object.Instantiate(DestroyableSingleton.CMJOLNCMAPD.AllPets[(int)Morphling.morphTarget.IDOFAMCIJKE.GKFOHNJHFOE]); Morphling.morphling.CurrentPet.transform.position = Morphling.morphling.transform.position; Morphling.morphling.CurrentPet.Source = Morphling.morphling; - Morphling.morphling.CurrentPet.Visible = Morphling.morphling.Visible; - PlayerControl.SetPlayerMaterialColors(Morphling.morphTarget.Data.ColorId, Morphling.morphling.CurrentPet.rend); + Morphling.morphling.CurrentPet.FHBHBMIJFID = Morphling.morphling.FHBHBMIJFID; + PlayerControl.SetPlayerMaterialColors(Morphling.morphTarget.IDOFAMCIJKE.JFHFMIKFHGG, Morphling.morphling.CurrentPet.rend); } else if (Morphling.morphling.CurrentPet) { - PlayerControl.SetPlayerMaterialColors(Morphling.morphTarget.Data.ColorId, Morphling.morphling.CurrentPet.rend); + PlayerControl.SetPlayerMaterialColors(Morphling.morphTarget.IDOFAMCIJKE.JFHFMIKFHGG, Morphling.morphling.CurrentPet.rend); } } } @@ -268,10 +237,10 @@ namespace TheOtherRoles // Set camouflaged look (overrides morphling morphed look if existent) if (Camouflager.camouflageTimer > 0f) { foreach (PlayerControl p in PlayerControl.AllPlayerControls) { - if (Seer.seer == null || Seer.seer != PlayerControl.LocalPlayer) - p.nameText.Text = ""; - p.myRend.material.SetColor("_BackColor", Color.grey); - p.myRend.material.SetColor("_BodyColor", Color.grey); + p.nameText.Text = ""; + p.LNMJKMLHMIM.material.SetColor("_BackColor", Palette.CALCLMEEPGL[6]); + p.LNMJKMLHMIM.material.SetColor("_BodyColor", Palette.CALCLMEEPGL[6]); + p.LNMJKMLHMIM.material.SetFloat("_Outline", 0f); p.HatRenderer.SetHat(0, 0); Helpers.setSkinWithAnim(p.MyPhysics, 0); if (p.CurrentPet) UnityEngine.Object.Destroy(p.CurrentPet.gameObject); @@ -305,8 +274,8 @@ namespace TheOtherRoles p.transform.localScale = new Vector3(scale, scale, 1f); p.nameText.Text += suffix; if (MeetingHud.Instance != null) - foreach (PlayerVoteArea player in MeetingHud.Instance.playerStates) - if (player.NameText != null && p.PlayerId == player.TargetPlayerId) + foreach (PlayerVoteArea player in MeetingHud.Instance.DHCOPOOJCLN) + if (player.NameText != null && p.PlayerId == player.HMPHKKGPLAG) player.NameText.Text += suffix; } else if (Morphling.morphling != null && Morphling.morphling == p && Morphling.morphTarget != null && Morphling.morphTarget == Child.child && Morphling.morphTimer > 0f) { @@ -325,8 +294,8 @@ namespace TheOtherRoles string suffix = "[AD653BFF] (Bounty)[FFFFFFFF]"; PlayerControl.LocalPlayer.nameText.Text += suffix; if (MeetingHud.Instance != null) - foreach (PlayerVoteArea player in MeetingHud.Instance.playerStates) - if (player.NameText != null && PlayerControl.LocalPlayer.PlayerId == player.TargetPlayerId) + foreach (PlayerVoteArea player in MeetingHud.Instance.DHCOPOOJCLN) + if (player.NameText != null && PlayerControl.LocalPlayer.PlayerId == player.HMPHKKGPLAG) player.NameText.Text += suffix; } } @@ -345,18 +314,18 @@ namespace TheOtherRoles foreach (Arrow arrow in Snitch.localArrows) arrow.arrow.SetActive(false); - if (Snitch.snitch == null || Snitch.snitch.Data.IsDead) return; + if (Snitch.snitch == null || Snitch.snitch.IDOFAMCIJKE.FGNJJFABIHJ) return; int numberOfTasks = 0; - GameData.PlayerInfo playerInfo = Snitch.snitch.Data; - if (!playerInfo.Disconnected && playerInfo.Tasks != null) { - for (int i = 0; i < playerInfo.Tasks.Count; i++) { - if (!playerInfo.Tasks[i].Complete) + GameData.OFKOJOKOOAK OFKOJOKOOAK = Snitch.snitch.IDOFAMCIJKE; + if (!OFKOJOKOOAK.GBPMEHJFECK && OFKOJOKOOAK.CLLMDIJHALO != null) { + for (int i = 0; i < OFKOJOKOOAK.CLLMDIJHALO.Count; i++) { + if (!OFKOJOKOOAK.CLLMDIJHALO[i].FNCBODEIJCN) numberOfTasks++; } } - if (PlayerControl.LocalPlayer.Data.IsImpostor && numberOfTasks <= Snitch.taskCountForImpostors) { + if (PlayerControl.LocalPlayer.IDOFAMCIJKE.CIDDOFDJHJH && numberOfTasks <= Snitch.taskCountForImpostors) { if (Snitch.localArrows.Count == 0) Snitch.localArrows.Add(new Arrow(Color.blue)); if (Snitch.localArrows.Count != 0 && Snitch.localArrows[0] != null) { Snitch.localArrows[0].arrow.SetActive(true); @@ -365,7 +334,7 @@ namespace TheOtherRoles } else if (PlayerControl.LocalPlayer == Snitch.snitch && numberOfTasks == 0) { int arrowIndex = 0; foreach (PlayerControl p in PlayerControl.AllPlayerControls) { - if (p.Data.IsImpostor && !p.Data.IsDead) { + if (p.IDOFAMCIJKE.CIDDOFDJHJH && !p.IDOFAMCIJKE.FGNJJFABIHJ) { if (arrowIndex >= Snitch.localArrows.Count) Snitch.localArrows.Add(new Arrow(Color.blue)); if (arrowIndex < Snitch.localArrows.Count && Snitch.localArrows[arrowIndex] != null) { Snitch.localArrows[arrowIndex].arrow.SetActive(true); @@ -379,7 +348,7 @@ namespace TheOtherRoles static void Postfix(HudManager __instance) { - if (AmongUsClient.Instance.GameState != InnerNet.InnerNetClient.GameStates.Started) return; + if (AmongUsClient.Instance.GameState != InnerNet.InnerNetClient.CJDCOJJNIGL.Started) return; CustomButton.HudUpdate(); resetNameTagsAndColors(); @@ -394,12 +363,8 @@ namespace TheOtherRoles mafiosoDeactivateKillButtonIfNecessary(__instance); // Janitor janitorDeactivateKillButton(__instance); - // Shifter - Helpers.removeTasksFromPlayer(Shifter.shifter); - // Seer update - seerUpdate(); - // Spy update(); - spyUpdate(); + // Timer updates + timerUpdate(); // Camouflager and Morphling camouflageAndMorphActions(); // Child diff --git a/Source Code/UsablesPatch.cs b/Source Code/UsablesPatch.cs index babcb11..92d0fb6 100644 --- a/Source Code/UsablesPatch.cs +++ b/Source Code/UsablesPatch.cs @@ -6,19 +6,26 @@ using UnityEngine; using System.Linq; using static TheOtherRoles.TheOtherRoles; using static TheOtherRoles.GameHistory; -using Reactor.Extensions; +using static TheOtherRoles.MapOptions; using System.Collections.Generic; +using SystemTypes = LGBKLKNAINN; +using Palette = GLNPIJPGGNJ; +using Constants = NFONDPLFBCP; +using PhysicsHelpers = IEPBCHBGDOA; +using TaskTypes = CBFIAGIGOFA; +using ImageNames = IKHMOFOFDHI; + namespace TheOtherRoles { [HarmonyPatch(typeof(Vent), "CanUse")] public static class VentCanUsePatch { - public static bool Prefix(Vent __instance, ref float __result, [HarmonyArgument(0)] GameData.PlayerInfo pc, [HarmonyArgument(1)] out bool canUse, [HarmonyArgument(2)] out bool couldUse) + public static bool Prefix(Vent __instance, ref float __result, [HarmonyArgument(0)] GameData.OFKOJOKOOAK pc, [HarmonyArgument(1)] out bool canUse, [HarmonyArgument(2)] out bool couldUse) { float num = float.MaxValue; - PlayerControl @object = pc.Object; + PlayerControl @object = pc.GPBBCHGPABL; bool roleCouldUse = false; @@ -28,23 +35,23 @@ namespace TheOtherRoles roleCouldUse = true; else if (Sidekick.canUseVents && Sidekick.sidekick != null && Sidekick.sidekick == @object) roleCouldUse = true; - else if (pc.IsImpostor) { + else if (pc.CIDDOFDJHJH) { if (Janitor.janitor != null && Janitor.janitor == PlayerControl.LocalPlayer) roleCouldUse = false; - else if (Mafioso.mafioso != null && Mafioso.mafioso == PlayerControl.LocalPlayer && Godfather.godfather != null && !Godfather.godfather.Data.IsDead) + else if (Mafioso.mafioso != null && Mafioso.mafioso == PlayerControl.LocalPlayer && Godfather.godfather != null && !Godfather.godfather.IDOFAMCIJKE.FGNJJFABIHJ) roleCouldUse = false; else roleCouldUse = true; } - couldUse = ((@object.inVent || roleCouldUse) && !pc.IsDead && (@object.CanMove || @object.inVent)); + couldUse = ((@object.inVent || roleCouldUse) && !pc.FGNJJFABIHJ && (@object.AMDJMEEHNIG || @object.inVent)); canUse = couldUse; if (canUse) { Vector2 truePosition = @object.GetTruePosition(); Vector3 position = __instance.transform.position; num = Vector2.Distance(truePosition, position); - canUse &= (num <= __instance.UsableDistance && !PhysicsHelpers.AnythingBetween(truePosition, position, Constants.ShipOnlyMask, false)); + canUse &= (num <= __instance.GBFKHOCBAOF && !PhysicsHelpers.GCFCONMBBOF(truePosition, position, Constants.NCOONMPDEDB, false)); } __result = num; return false; @@ -56,7 +63,7 @@ namespace TheOtherRoles public static void Prefix(Vent __instance) { bool flag; bool flag2; - __instance.CanUse(PlayerControl.LocalPlayer.Data, out flag, out flag2); + __instance.CanUse(PlayerControl.LocalPlayer.IDOFAMCIJKE, out flag, out flag2); if (flag && !PlayerControl.LocalPlayer.inVent) localVentEnterTimePoint = DateTime.UtcNow; } @@ -65,13 +72,13 @@ namespace TheOtherRoles [HarmonyPatch(typeof(UseButtonManager), nameof(UseButtonManager.SetTarget))] class UseButtonSetTargetPatch { static void Postfix(UseButtonManager __instance) { - if (__instance.Field_3 != null) return; + if (__instance.FKANCEFMKPH != null) return; // Mafia sabotage button render patch bool blockSabotageJanitor = (Janitor.janitor != null && Janitor.janitor == PlayerControl.LocalPlayer); - bool blockSabotageMafioso = (Mafioso.mafioso != null && Mafioso.mafioso == PlayerControl.LocalPlayer && Godfather.godfather != null && !Godfather.godfather.Data.IsDead); + bool blockSabotageMafioso = (Mafioso.mafioso != null && Mafioso.mafioso == PlayerControl.LocalPlayer && Godfather.godfather != null && !Godfather.godfather.IDOFAMCIJKE.FGNJJFABIHJ); if (blockSabotageJanitor || blockSabotageMafioso) { - // __instance.UseButton.sprite = __instance.UseImage; + __instance.UseButton.sprite = DestroyableSingleton.CMJOLNCMAPD.GetImage(ImageNames.UseButton); __instance.UseButton.color = new Color(1f, 1f, 1f, 0.3f); } @@ -81,11 +88,11 @@ namespace TheOtherRoles [HarmonyPatch(typeof(UseButtonManager), nameof(UseButtonManager.DoClick))] class UseButtonDoClickPatch { static bool Prefix(UseButtonManager __instance) { - if (__instance.Field_3 != null) return true; + if (__instance.FKANCEFMKPH != null) return true; // Mafia sabotage button click patch bool blockSabotageJanitor = (Janitor.janitor != null && Janitor.janitor == PlayerControl.LocalPlayer); - bool blockSabotageMafioso = (Mafioso.mafioso != null && Mafioso.mafioso == PlayerControl.LocalPlayer && Godfather.godfather != null && !Godfather.godfather.Data.IsDead); + bool blockSabotageMafioso = (Mafioso.mafioso != null && Mafioso.mafioso == PlayerControl.LocalPlayer && Godfather.godfather != null && !Godfather.godfather.IDOFAMCIJKE.FGNJJFABIHJ); if (blockSabotageJanitor || blockSabotageMafioso) return false; return true; @@ -103,6 +110,18 @@ namespace TheOtherRoles __instance.OpenLid.gameObject.SetActive(false); __instance.ButtonActive = false; } + + // Handle max number of meetings + if (__instance.MJMOOPLLNPO == 1) { + int localRemaining = PlayerControl.LocalPlayer.RemainingEmergencies; + int teamRemaining = Mathf.Max(0, maxNumberOfMeetings - meetingsCount); + int remaining = Mathf.Min(localRemaining, (Mayor.mayor != null && Mayor.mayor == PlayerControl.LocalPlayer) ? 1 : teamRemaining); + __instance.NumberText.Text = $"{localRemaining.ToString()} and the ship has {teamRemaining.ToString()}"; + __instance.ButtonActive = remaining > 0; + __instance.ClosedLid.gameObject.SetActive(!__instance.ButtonActive); + __instance.OpenLid.gameObject.SetActive(__instance.ButtonActive); + return; + } } } @@ -129,22 +148,22 @@ namespace TheOtherRoles [HarmonyPatch(typeof(VitalsMinigame), nameof(VitalsMinigame.Update))] class VitalsMinigamePatch { static void Postfix(VitalsMinigame __instance) { - // Spy show time since death - bool showSpyInfo = Spy.spy != null && Spy.spy == PlayerControl.LocalPlayer && Spy.spyTimer > 0; - for (int k = 0; k < __instance.vitals.Length; k++) + // Hacker show time since death + bool showHackerInfo = Hacker.hacker != null && Hacker.hacker == PlayerControl.LocalPlayer && Hacker.hackerTimer > 0; + for (int k = 0; k < __instance.MCCBOPIEOEC.Length; k++) { - VitalsPanel vitalsPanel = __instance.vitals[k]; - GameData.PlayerInfo playerInfo = GameData.Instance.AllPlayers[k]; + VitalsPanel vitalsPanel = __instance.MCCBOPIEOEC[k]; + GameData.OFKOJOKOOAK OFKOJOKOOAK = GameData.Instance.AllPlayers[k]; if (vitalsPanel.IsDead) { - DeadPlayer deadPlayer = deadPlayers?.Where(x => x.player?.PlayerId == playerInfo?.PlayerId)?.FirstOrDefault(); + DeadPlayer deadPlayer = deadPlayers?.Where(x => x.player?.PlayerId == OFKOJOKOOAK?.GMBAIPNOKLP)?.FirstOrDefault(); if (deadPlayer != null && deadPlayer.timeOfDeath != null) { float timeSinceDeath = ((float)(DateTime.UtcNow - deadPlayer.timeOfDeath).TotalMilliseconds); - if (showSpyInfo) + if (showHackerInfo) vitalsPanel.Text.Text = Math.Round(timeSinceDeath / 1000) + "s"; else - vitalsPanel.Text.Text = DestroyableSingleton.Instance.GetString(Palette.ShortColorNames[(int)playerInfo.ColorId], new UnhollowerBaseLib.Il2CppReferenceArray(0)); + vitalsPanel.Text.Text = DestroyableSingleton.CMJOLNCMAPD.GetString(Palette.OCCIKHJPJPK[(int)OFKOJOKOOAK.JFHFMIKFHGG], new UnhollowerBaseLib.Il2CppReferenceArray(0)); } } } @@ -158,29 +177,29 @@ namespace TheOtherRoles [HarmonyPatch(typeof(MapCountOverlay), nameof(MapCountOverlay.Update))] class MapCountOverlayUpdatePatch { static bool Prefix(MapCountOverlay __instance) { - // Save colors for the Spy - __instance.timer += Time.deltaTime; - if (__instance.timer < 0.1f) + // Save colors for the Hacker + __instance.HAHFHCCIEGH += Time.deltaTime; + if (__instance.HAHFHCCIEGH < 0.1f) { return false; } - __instance.timer = 0f; + __instance.HAHFHCCIEGH = 0f; players = new Dictionary>(); bool commsActive = false; foreach (PlayerTask task in PlayerControl.LocalPlayer.myTasks) if (task.TaskType == TaskTypes.FixComms) commsActive = true; - if (!__instance.isSab && commsActive) + if (!__instance.KGMLJDGMIND && commsActive) { - __instance.isSab = true; - __instance.BackgroundColor.SetColor(Palette.DisabledGrey); + __instance.KGMLJDGMIND = true; + __instance.BackgroundColor.SetColor(Palette.JMELLHINKGM); __instance.SabotageText.gameObject.SetActive(true); return false; } - if (__instance.isSab && !commsActive) + if (__instance.KGMLJDGMIND && !commsActive) { - __instance.isSab = false; + __instance.KGMLJDGMIND = false; __instance.BackgroundColor.SetColor(Color.green); __instance.SabotageText.gameObject.SetActive(false); } @@ -193,30 +212,39 @@ namespace TheOtherRoles if (!commsActive) { - PlainShipRoom plainShipRoom = ShipStatus.Instance.FastRooms[counterArea.RoomType]; + PlainShipRoom plainShipRoom = ShipStatus.Instance.EMIBABGLHIO[counterArea.RoomType]; if (plainShipRoom != null && plainShipRoom.roomArea) { - int num = plainShipRoom.roomArea.OverlapCollider(__instance.filter, __instance.buffer); + int num = plainShipRoom.roomArea.OverlapCollider(__instance.CGAANOHJEKD, __instance.BLDONECDJFJ); int num2 = num; for (int j = 0; j < num; j++) { - Collider2D collider2D = __instance.buffer[j]; + Collider2D collider2D = __instance.BLDONECDJFJ[j]; if (!(collider2D.tag == "DeadBody")) { PlayerControl component = collider2D.GetComponent(); - if (!component || component.Data == null || component.Data.Disconnected || component.Data.IsDead) + if (!component || component.IDOFAMCIJKE == null || component.IDOFAMCIJKE.GBPMEHJFECK || component.IDOFAMCIJKE.FGNJJFABIHJ) { num2--; - } else { - roomColors.Add(Palette.PlayerColors[component.Data.ColorId]); + } else if (component?.LNMJKMLHMIM?.material != null) { + Color color = component.LNMJKMLHMIM.material.GetColor("_BodyColor"); + if (Hacker.onlyColorType) { + var id = Mathf.Max(0, Palette.CALCLMEEPGL.IndexOf(color)); + color = Helpers.isLighterColor((byte)id) ? Palette.CALCLMEEPGL[7] : Palette.CALCLMEEPGL[6]; + } + roomColors.Add(color); } } else { DeadBody component = collider2D.GetComponent(); if (component) { - GameData.PlayerInfo playerInfo = GameData.Instance.GetPlayerById(component.ParentId); - if (playerInfo != null) - roomColors.Add(Palette.PlayerColors[playerInfo.ColorId]); + GameData.OFKOJOKOOAK OFKOJOKOOAK = GameData.Instance.GetPlayerById(component.ParentId); + if (OFKOJOKOOAK != null) { + var color = Palette.CALCLMEEPGL[OFKOJOKOOAK.JFHFMIKFHGG]; + if (Hacker.onlyColorType) + color = Helpers.isLighterColor(OFKOJOKOOAK.JFHFMIKFHGG) ? Palette.CALCLMEEPGL[7] : Palette.CALCLMEEPGL[6]; + roomColors.Add(color); + } } } } @@ -241,19 +269,19 @@ namespace TheOtherRoles private static Sprite defaultIcon; static void Postfix(CounterArea __instance) { - // Spy display saved colors on the admin panel - bool showSpyInfo = Spy.spy != null && Spy.spy == PlayerControl.LocalPlayer && Spy.spyTimer > 0; + // Hacker display saved colors on the admin panel + bool showHackerInfo = Hacker.hacker != null && Hacker.hacker == PlayerControl.LocalPlayer && Hacker.hackerTimer > 0; if (players.ContainsKey(__instance.RoomType)) { List colors = players[__instance.RoomType]; - for (int i = 0; i < __instance.myIcons.Count; i++) { - PoolableBehavior icon = __instance.myIcons[i]; + for (int i = 0; i < __instance.KIFEIHAMMJC.Count; i++) { + PoolableBehavior icon = __instance.KIFEIHAMMJC[i]; SpriteRenderer renderer = icon.GetComponent(); if (renderer != null) { if (defaultIcon == null) defaultIcon = renderer.sprite; - if (showSpyInfo && colors.Count > i && Spy.getAdminTableIconSprite() != null) { - renderer.sprite = Spy.getAdminTableIconSprite(); + if (showHackerInfo && colors.Count > i && Hacker.getAdminTableIconSprite() != null) { + renderer.sprite = Hacker.getAdminTableIconSprite(); renderer.color = colors[i]; } else { renderer.sprite = defaultIcon;