1+ using HarmonyLib ;
2+ using UnityEngine ;
3+ using Object = UnityEngine . Object ;
4+ using Il2CppInterop . Runtime . InteropTypes . Arrays ;
5+ using System . Linq ;
6+ using TownOfUs . CrewmateRoles . MedicMod ;
7+ using TownOfUs . Extensions ;
8+ using TownOfUs . Patches ;
9+ using TownOfUs . Roles ;
10+ using TownOfUs . Roles . Modifiers ;
11+ using Reactor . Utilities . Extensions ;
12+ using TownOfUs . CrewmateRoles . ImitatorMod ;
13+ using TownOfUs . CrewmateRoles . SwapperMod ;
14+ using TownOfUs . CrewmateRoles . VigilanteMod ;
15+ using TownOfUs . ImpostorRoles . BlackmailerMod ;
16+ using TownOfUs . Modifiers . AssassinMod ;
17+ using TownOfUs . NeutralRoles . DoomsayerMod ;
18+ using UnityEngine . UI ;
19+
20+ namespace TownOfUs . CrewmateRoles . HunterMod
21+ {
22+ [ HarmonyPatch ( typeof ( MeetingHud ) , nameof ( MeetingHud . CastVote ) ) ]
23+ internal class CastVote
24+ {
25+ private static void Postfix ( MeetingHud __instance , [ HarmonyArgument ( 0 ) ] byte srcPlayerId , [ HarmonyArgument ( 1 ) ] byte suspectPlayerId )
26+ {
27+ var votingPlayer = Utils . PlayerById ( srcPlayerId ) ;
28+ var suspectPlayer = Utils . PlayerById ( suspectPlayerId ) ;
29+ if ( ! suspectPlayer . Is ( RoleEnum . Hunter ) ) return ;
30+ var hunter = Role . GetRole < Hunter > ( suspectPlayer ) ;
31+ hunter . LastVoted = votingPlayer ;
32+ }
33+ }
34+
35+ [ HarmonyPatch ( typeof ( ExileController ) , nameof ( ExileController . BeginForGameplay ) ) ]
36+ internal class MeetingExiledEnd
37+ {
38+ private static void Postfix ( ExileController __instance )
39+ {
40+ var exiled = __instance . initData . networkedPlayer ;
41+ if ( exiled == null ) return ;
42+ var player = exiled . Object ;
43+ if ( player . Is ( RoleEnum . Hunter ) && CustomGameOptions . RetributionOnVote )
44+ {
45+ var hunter = Role . GetRole < Hunter > ( player ) ;
46+ if ( hunter . LastVoted != null && hunter . LastVoted != player && ! hunter . LastVoted . Is ( RoleEnum . Pestilence ) )
47+ {
48+ foreach ( var role in Role . AllRoles . Where ( x => x . RoleType == RoleEnum . Executioner ) )
49+ {
50+ var exe = ( Executioner ) role ;
51+ if ( exe . target == player ) return ;
52+ }
53+ Utils . Rpc ( CustomRPC . Retribution , hunter . Player . PlayerId , hunter . LastVoted . PlayerId ) ;
54+ Retribution . MurderPlayer ( hunter , hunter . LastVoted ) ;
55+ }
56+ }
57+ foreach ( var role in Role . AllRoles . Where ( x => x . RoleType == RoleEnum . Hunter ) )
58+ {
59+ var hunter = ( Hunter ) role ;
60+ hunter . LastVoted = null ;
61+ }
62+ }
63+ }
64+
65+ public class Retribution
66+ {
67+ public static void MurderPlayer ( Hunter hunter , PlayerControl player )
68+ {
69+ if ( player . Is ( Faction . Crewmates ) ) hunter . IncorrectKills += 1 ;
70+ else hunter . CorrectKills += 1 ;
71+ MurderPlayer ( player ) ;
72+ }
73+
74+ public static void MurderPlayer (
75+ PlayerControl player ,
76+ bool checkLover = true
77+ )
78+ {
79+ var hudManager = DestroyableSingleton < HudManager > . Instance ;
80+ if ( checkLover )
81+ {
82+ SoundManager . Instance . PlaySound ( player . KillSfx , false , 0.8f ) ;
83+ hudManager . KillOverlay . ShowKillAnimation ( player . Data , player . Data ) ;
84+ }
85+ var amOwner = player . AmOwner ;
86+ if ( amOwner )
87+ {
88+ Utils . ShowDeadBodies = true ;
89+ hudManager . ShadowQuad . gameObject . SetActive ( false ) ;
90+ player . nameText ( ) . GetComponent < MeshRenderer > ( ) . material . SetInt ( "_Mask" , 0 ) ;
91+ player . RpcSetScanner ( false ) ;
92+ ImportantTextTask importantTextTask = new GameObject ( "_Player" ) . AddComponent < ImportantTextTask > ( ) ;
93+ importantTextTask . transform . SetParent ( AmongUsClient . Instance . transform , false ) ;
94+ if ( ! GameOptionsManager . Instance . currentNormalGameOptions . GhostsDoTasks )
95+ {
96+ for ( int i = 0 ; i < player . myTasks . Count ; i ++ )
97+ {
98+ PlayerTask playerTask = player . myTasks . ToArray ( ) [ i ] ;
99+ playerTask . OnRemove ( ) ;
100+ Object . Destroy ( playerTask . gameObject ) ;
101+ }
102+
103+ player . myTasks . Clear ( ) ;
104+ importantTextTask . Text = DestroyableSingleton < TranslationController > . Instance . GetString (
105+ StringNames . GhostIgnoreTasks ,
106+ new Il2CppReferenceArray < Il2CppSystem . Object > ( 0 )
107+ ) ;
108+ }
109+ else
110+ {
111+ importantTextTask . Text = DestroyableSingleton < TranslationController > . Instance . GetString (
112+ StringNames . GhostDoTasks ,
113+ new Il2CppReferenceArray < Il2CppSystem . Object > ( 0 ) ) ;
114+ }
115+
116+ player . myTasks . Insert ( 0 , importantTextTask ) ;
117+ }
118+ player . Die ( DeathReason . Kill , false ) ;
119+ if ( checkLover && player . IsLover ( ) && CustomGameOptions . BothLoversDie )
120+ {
121+ var otherLover = Modifier . GetModifier < Lover > ( player ) . OtherLover . Player ;
122+ if ( ! otherLover . Is ( RoleEnum . Pestilence ) ) MurderPlayer ( otherLover , false ) ;
123+ }
124+
125+ var deadPlayer = new DeadPlayer
126+ {
127+ PlayerId = player . PlayerId ,
128+ KillerId = player . PlayerId ,
129+ KillTime = System . DateTime . UtcNow ,
130+ } ;
131+
132+ Murder . KilledPlayers . Add ( deadPlayer ) ;
133+
134+ AddHauntPatch . AssassinatedPlayers . Add ( player ) ;
135+ }
136+ }
137+ }
0 commit comments