From a67a5c58a12459a695efbc93403011c7b918ac48 Mon Sep 17 00:00:00 2001 From: Gurge44 Date: Wed, 18 Feb 2026 19:46:07 +0100 Subject: [PATCH] MAY have fixed T1-T2 kicking.... also reverted GameOptionsMenuPatch.cs changes to 7.2.2 and did some other fixes --- .editorconfig | 103 +-- EHR.csproj | 2 +- EHR.sln.DotSettings | 7 + Gamemodes/StopAndGo.cs | 39 +- Modules/CustomNetObject.cs | 5 + Modules/CustomSounds.cs | 17 +- Modules/Debugger.cs | 21 +- Modules/EmbeddedDeps.cs | 3 +- Modules/ErrorText.cs | 2 +- Modules/FixedUpdateCaller.cs | 7 +- .../GameOptionsSender/GameOptionsSender.cs | 44 +- .../PlayerGameOptionsSender.cs | 2 +- Modules/RPC.cs | 4 +- Modules/Utils.cs | 16 +- Modules/Zoom.cs | 26 +- Patches/ChatCommandPatch.cs | 2 +- Patches/CheckGameEndPatch.cs | 8 +- Patches/ClientPatch.cs | 20 +- Patches/ControlPatch.cs | 6 +- Patches/CredentialsPatch.cs | 18 +- Patches/GameOptionsMenuPatch.cs | 614 +++++++++--------- Patches/HudPatch.cs | 44 +- Patches/OutroPatch.cs | 5 +- Patches/ShipStatusPatch.cs | 2 +- Roles/Standard/Addons/Common/Asthmatic.cs | 2 +- Roles/Standard/Crewmate/Chaos/Tornado.cs | 14 +- Roles/Standard/Crewmate/Support/Altruist.cs | 2 +- Roles/Standard/Neutral/Killing/Necromancer.cs | 2 +- 28 files changed, 482 insertions(+), 555 deletions(-) diff --git a/.editorconfig b/.editorconfig index fd9f24939..3f0cacf93 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,50 +1,33 @@ [*.cs] # CA2211: Non-constant fields should not be visible -dotnet_diagnostic.ca2211.severity = none # IDE0060: Remove unused parameter -dotnet_diagnostic.ide0060.severity = none csharp_using_directive_placement = outside_namespace:silent csharp_prefer_simple_using_statement = true:suggestion csharp_prefer_braces = when_multiline:none csharp_style_namespace_declarations = file_scoped:none -csharp_style_prefer_method_group_conversion = true:silent -csharp_style_prefer_top_level_statements = true:silent -csharp_style_prefer_primary_constructors = true:suggestion csharp_style_expression_bodied_operators = false:silent csharp_style_expression_bodied_indexers = true:silent csharp_style_expression_bodied_lambdas = true:silent csharp_style_expression_bodied_local_functions = false:silent csharp_indent_labels = one_less_than_current csharp_style_throw_expression = true:suggestion -csharp_style_prefer_null_check_over_type_check = true:suggestion csharp_prefer_simple_default_expression = true:suggestion -csharp_style_prefer_local_over_anonymous_function = true:suggestion csharp_style_prefer_index_operator = true:suggestion csharp_style_prefer_range_operator = true:suggestion -csharp_style_implicit_object_creation_when_type_is_apparent = true:suggestion -csharp_style_prefer_tuple_swap = true:suggestion csharp_style_prefer_utf8_string_literals = true:suggestion csharp_style_inlined_variable_declaration = true:suggestion csharp_style_deconstructed_variable_declaration = true:suggestion csharp_style_unused_value_assignment_preference = discard_variable:suggestion csharp_style_unused_value_expression_statement_preference = discard_variable:silent csharp_prefer_static_local_function = true:suggestion -csharp_style_prefer_readonly_struct = true:suggestion -csharp_style_prefer_readonly_struct_member = true:suggestion -csharp_style_allow_embedded_statements_on_same_line_experimental = true:silent -csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true:silent -csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true:silent -csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true:silent -csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true:silent csharp_style_conditional_delegate_call = true:suggestion csharp_style_prefer_switch_expression = true:suggestion csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion csharp_style_prefer_pattern_matching = true:silent csharp_style_pattern_matching_over_as_with_null_check = true:suggestion csharp_style_prefer_not_pattern = true:suggestion -csharp_style_prefer_extended_property_pattern = true:suggestion csharp_style_var_for_built_in_types = false:none csharp_style_var_when_type_is_apparent = true:none csharp_style_var_elsewhere = false:none @@ -99,82 +82,42 @@ resharper_use_indent_from_vs = false # Microsoft .NET properties csharp_new_line_before_members_in_object_initializers = false csharp_preferred_modifier_order = public, private, protected, internal, file, new, static, abstract, virtual, sealed, readonly, override, extern, unsafe, volatile, async, required:suggestion -dotnet_naming_rule.constants_rule.import_to_resharper = True -dotnet_naming_rule.constants_rule.resharper_description = Constant fields (not private) -dotnet_naming_rule.constants_rule.resharper_guid = 669e5282-fb4b-4e90-91e7-07d269d04b60 dotnet_naming_rule.constants_rule.severity = suggestion dotnet_naming_rule.constants_rule.style = upper_camel_case_style dotnet_naming_rule.constants_rule.symbols = constants_symbols -dotnet_naming_rule.interface_should_be_begins_with_i_rule.import_to_resharper = True -dotnet_naming_rule.interface_should_be_begins_with_i_rule.resharper_description = interface_should_be_begins_with_i -dotnet_naming_rule.interface_should_be_begins_with_i_rule.resharper_guid = 60bf1ae3-25da-46bc-8281-c816299091c0 dotnet_naming_rule.interface_should_be_begins_with_i_rule.severity = suggestion dotnet_naming_rule.interface_should_be_begins_with_i_rule.style = i_upper_camel_case_style dotnet_naming_rule.interface_should_be_begins_with_i_rule.symbols = interface_should_be_begins_with_i_symbols -dotnet_naming_rule.non_field_members_should_be_pascal_case_rule.import_to_resharper = True -dotnet_naming_rule.non_field_members_should_be_pascal_case_rule.resharper_description = non_field_members_should_be_pascal_case -dotnet_naming_rule.non_field_members_should_be_pascal_case_rule.resharper_guid = c4363532-209c-4073-90f0-b0d1296bc910 dotnet_naming_rule.non_field_members_should_be_pascal_case_rule.severity = none dotnet_naming_rule.non_field_members_should_be_pascal_case_rule.style = upper_camel_case_style dotnet_naming_rule.non_field_members_should_be_pascal_case_rule.symbols = non_field_members_should_be_pascal_case_symbols -dotnet_naming_rule.parameters_rule.import_to_resharper = True -dotnet_naming_rule.parameters_rule.resharper_description = Parameters -dotnet_naming_rule.parameters_rule.resharper_guid = 8a85b61a-1024-4f87-b9ef-1fdae19930a1 -dotnet_naming_rule.parameters_rule.resharper_style = aaBb, __ + aaBb dotnet_naming_rule.parameters_rule.severity = suggestion dotnet_naming_rule.parameters_rule.style = lower_camel_case_style dotnet_naming_rule.parameters_rule.symbols = parameters_symbols -dotnet_naming_rule.private_constants_rule.import_to_resharper = True -dotnet_naming_rule.private_constants_rule.resharper_description = Constant fields (private) -dotnet_naming_rule.private_constants_rule.resharper_guid = 236f7aa5-7b06-43ca-bf2a-9b31bfcff09a dotnet_naming_rule.private_constants_rule.severity = suggestion dotnet_naming_rule.private_constants_rule.style = upper_camel_case_style dotnet_naming_rule.private_constants_rule.symbols = private_constants_symbols -dotnet_naming_rule.private_instance_fields_rule.import_to_resharper = True -dotnet_naming_rule.private_instance_fields_rule.resharper_description = Instance fields (private) -dotnet_naming_rule.private_instance_fields_rule.resharper_guid = 4a98fdf6-7d98-4f5a-afeb-ea44ad98c70c dotnet_naming_rule.private_instance_fields_rule.severity = none dotnet_naming_rule.private_instance_fields_rule.style = lower_camel_case_style_1 dotnet_naming_rule.private_instance_fields_rule.symbols = private_instance_fields_symbols -dotnet_naming_rule.private_static_fields_rule.import_to_resharper = True -dotnet_naming_rule.private_static_fields_rule.resharper_description = Static fields (private) -dotnet_naming_rule.private_static_fields_rule.resharper_guid = f9fce829-e6f4-4cb2-80f1-5497c44f51df dotnet_naming_rule.private_static_fields_rule.severity = suggestion dotnet_naming_rule.private_static_fields_rule.style = upper_camel_case_style dotnet_naming_rule.private_static_fields_rule.symbols = private_static_fields_symbols -dotnet_naming_rule.private_static_readonly_rule.import_to_resharper = True -dotnet_naming_rule.private_static_readonly_rule.resharper_description = Static readonly fields (private) -dotnet_naming_rule.private_static_readonly_rule.resharper_guid = 15b5b1f1-457c-4ca6-b278-5615aedc07d3 dotnet_naming_rule.private_static_readonly_rule.severity = suggestion dotnet_naming_rule.private_static_readonly_rule.style = upper_camel_case_style dotnet_naming_rule.private_static_readonly_rule.symbols = private_static_readonly_symbols -dotnet_naming_rule.public_fields_rule.import_to_resharper = True -dotnet_naming_rule.public_fields_rule.resharper_description = Instance fields (not private) -dotnet_naming_rule.public_fields_rule.resharper_guid = 53eecf85-d821-40e8-ac97-fdb734542b84 dotnet_naming_rule.public_fields_rule.severity = none dotnet_naming_rule.public_fields_rule.style = upper_camel_case_style dotnet_naming_rule.public_fields_rule.symbols = public_fields_symbols -dotnet_naming_rule.public_static_fields_rule.import_to_resharper = True -dotnet_naming_rule.public_static_fields_rule.resharper_description = Static fields (not private) -dotnet_naming_rule.public_static_fields_rule.resharper_guid = 70345118-4b40-4ece-937c-bbeb7a0b2e70 dotnet_naming_rule.public_static_fields_rule.severity = suggestion dotnet_naming_rule.public_static_fields_rule.style = upper_camel_case_style dotnet_naming_rule.public_static_fields_rule.symbols = public_static_fields_symbols -dotnet_naming_rule.static_readonly_rule.import_to_resharper = True -dotnet_naming_rule.static_readonly_rule.resharper_description = Static readonly fields (not private) -dotnet_naming_rule.static_readonly_rule.resharper_guid = c873eafb-d57f-481d-8c93-77f6863c2f88 dotnet_naming_rule.static_readonly_rule.severity = suggestion dotnet_naming_rule.static_readonly_rule.style = upper_camel_case_style dotnet_naming_rule.static_readonly_rule.symbols = static_readonly_symbols -dotnet_naming_rule.types_should_be_pascal_case_rule.import_to_resharper = True -dotnet_naming_rule.types_should_be_pascal_case_rule.resharper_description = types_should_be_pascal_case -dotnet_naming_rule.types_should_be_pascal_case_rule.resharper_guid = 749d8538-ec25-40b6-87c8-0ec37cfd4ba4 dotnet_naming_rule.types_should_be_pascal_case_rule.severity = none dotnet_naming_rule.types_should_be_pascal_case_rule.style = upper_camel_case_style dotnet_naming_rule.types_should_be_pascal_case_rule.symbols = types_should_be_pascal_case_symbols -dotnet_naming_rule.unity_serialized_field_rule.import_to_resharper = True -dotnet_naming_rule.unity_serialized_field_rule.resharper_description = Unity serialized field -dotnet_naming_rule.unity_serialized_field_rule.resharper_guid = 5f0fdb63-c892-4d2c-9324-15c80b22a7ef dotnet_naming_rule.unity_serialized_field_rule.severity = suggestion dotnet_naming_rule.unity_serialized_field_rule.style = lower_camel_case_style dotnet_naming_rule.unity_serialized_field_rule.symbols = unity_serialized_field_symbols @@ -187,69 +130,37 @@ dotnet_naming_style.upper_camel_case_style.capitalization = pascal_case dotnet_naming_symbols.constants_symbols.applicable_accessibilities = public, internal, protected, protected_internal, private_protected dotnet_naming_symbols.constants_symbols.applicable_kinds = field dotnet_naming_symbols.constants_symbols.required_modifiers = const -dotnet_naming_symbols.constants_symbols.resharper_applicable_kinds = constant_field -dotnet_naming_symbols.constants_symbols.resharper_required_modifiers = any dotnet_naming_symbols.interface_should_be_begins_with_i_symbols.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected dotnet_naming_symbols.interface_should_be_begins_with_i_symbols.applicable_kinds = interface -dotnet_naming_symbols.interface_should_be_begins_with_i_symbols.resharper_applicable_kinds = interface -dotnet_naming_symbols.interface_should_be_begins_with_i_symbols.resharper_required_modifiers = any dotnet_naming_symbols.non_field_members_should_be_pascal_case_symbols.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected dotnet_naming_symbols.non_field_members_should_be_pascal_case_symbols.applicable_kinds = event, method, property -dotnet_naming_symbols.non_field_members_should_be_pascal_case_symbols.resharper_applicable_kinds = property, event, method -dotnet_naming_symbols.non_field_members_should_be_pascal_case_symbols.resharper_required_modifiers = any dotnet_naming_symbols.parameters_symbols.applicable_accessibilities = * dotnet_naming_symbols.parameters_symbols.applicable_kinds = parameter -dotnet_naming_symbols.parameters_symbols.resharper_applicable_kinds = parameter -dotnet_naming_symbols.parameters_symbols.resharper_required_modifiers = any dotnet_naming_symbols.private_constants_symbols.applicable_accessibilities = private dotnet_naming_symbols.private_constants_symbols.applicable_kinds = field dotnet_naming_symbols.private_constants_symbols.required_modifiers = const -dotnet_naming_symbols.private_constants_symbols.resharper_applicable_kinds = constant_field -dotnet_naming_symbols.private_constants_symbols.resharper_required_modifiers = any dotnet_naming_symbols.private_instance_fields_symbols.applicable_accessibilities = private dotnet_naming_symbols.private_instance_fields_symbols.applicable_kinds = field -dotnet_naming_symbols.private_instance_fields_symbols.resharper_applicable_kinds = field, readonly_field -dotnet_naming_symbols.private_instance_fields_symbols.resharper_required_modifiers = instance dotnet_naming_symbols.private_static_fields_symbols.applicable_accessibilities = private dotnet_naming_symbols.private_static_fields_symbols.applicable_kinds = field dotnet_naming_symbols.private_static_fields_symbols.required_modifiers = static -dotnet_naming_symbols.private_static_fields_symbols.resharper_applicable_kinds = field -dotnet_naming_symbols.private_static_fields_symbols.resharper_required_modifiers = static dotnet_naming_symbols.private_static_readonly_symbols.applicable_accessibilities = private dotnet_naming_symbols.private_static_readonly_symbols.applicable_kinds = field dotnet_naming_symbols.private_static_readonly_symbols.required_modifiers = readonly, static -dotnet_naming_symbols.private_static_readonly_symbols.resharper_applicable_kinds = readonly_field -dotnet_naming_symbols.private_static_readonly_symbols.resharper_required_modifiers = static dotnet_naming_symbols.public_fields_symbols.applicable_accessibilities = public, internal, protected, protected_internal, private_protected dotnet_naming_symbols.public_fields_symbols.applicable_kinds = field -dotnet_naming_symbols.public_fields_symbols.resharper_applicable_kinds = field, readonly_field -dotnet_naming_symbols.public_fields_symbols.resharper_required_modifiers = instance dotnet_naming_symbols.public_static_fields_symbols.applicable_accessibilities = public, internal, protected, protected_internal, private_protected dotnet_naming_symbols.public_static_fields_symbols.applicable_kinds = field dotnet_naming_symbols.public_static_fields_symbols.required_modifiers = static -dotnet_naming_symbols.public_static_fields_symbols.resharper_applicable_kinds = field -dotnet_naming_symbols.public_static_fields_symbols.resharper_required_modifiers = static dotnet_naming_symbols.static_readonly_symbols.applicable_accessibilities = public, internal, protected, protected_internal, private_protected dotnet_naming_symbols.static_readonly_symbols.applicable_kinds = field dotnet_naming_symbols.static_readonly_symbols.required_modifiers = readonly, static -dotnet_naming_symbols.static_readonly_symbols.resharper_applicable_kinds = readonly_field -dotnet_naming_symbols.static_readonly_symbols.resharper_required_modifiers = static dotnet_naming_symbols.types_should_be_pascal_case_symbols.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected dotnet_naming_symbols.types_should_be_pascal_case_symbols.applicable_kinds = class, enum, interface, struct -dotnet_naming_symbols.types_should_be_pascal_case_symbols.resharper_applicable_kinds = class, struct, interface, enum -dotnet_naming_symbols.types_should_be_pascal_case_symbols.resharper_required_modifiers = any dotnet_naming_symbols.unity_serialized_field_symbols.applicable_accessibilities = * dotnet_naming_symbols.unity_serialized_field_symbols.applicable_kinds = -dotnet_naming_symbols.unity_serialized_field_symbols.resharper_applicable_kinds = unity_serialised_field -dotnet_naming_symbols.unity_serialized_field_symbols.resharper_required_modifiers = instance -dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:none -dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:none -dotnet_style_parentheses_in_relational_binary_operators = never_if_unnecessary:none -dotnet_style_qualification_for_event = false:none -dotnet_style_qualification_for_method = false:none # Standard properties -end_of_line = crlf # ReSharper inspection severities resharper_arrange_accessor_owner_body_highlighting = none @@ -280,8 +191,8 @@ resharper_mvc_view_not_resolved_highlighting = warning resharper_razor_assembly_not_resolved_highlighting = warning resharper_switch_statement_handles_some_known_enum_values_with_default_highlighting = none resharper_switch_statement_missing_some_enum_cases_no_default_highlighting = none -resharper_unity_performance_critical_code_invocation_highlighting = none -resharper_unity_performance_critical_code_null_comparison_highlighting = none +resharper_unity_performance_critical_code_invocation_highlighting = hint +resharper_unity_performance_critical_code_null_comparison_highlighting = warning resharper_web_config_module_not_resolved_highlighting = warning resharper_web_config_type_not_resolved_highlighting = warning resharper_web_config_wrong_module_highlighting = warning @@ -324,11 +235,6 @@ dotnet_naming_style.begins_with_i.required_suffix = dotnet_naming_style.begins_with_i.word_separator = dotnet_naming_style.begins_with_i.capitalization = pascal_case -dotnet_naming_style.pascal_case.required_prefix = -dotnet_naming_style.pascal_case.required_suffix = -dotnet_naming_style.pascal_case.word_separator = -dotnet_naming_style.pascal_case.capitalization = pascal_case - dotnet_naming_style.pascal_case.required_prefix = dotnet_naming_style.pascal_case.required_suffix = dotnet_naming_style.pascal_case.word_separator = @@ -339,8 +245,6 @@ dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggesti dotnet_style_prefer_auto_properties = true:silent dotnet_style_object_initializer = true:suggestion dotnet_style_operator_placement_when_wrapping = beginning_of_line -tab_width = 4 -indent_size = 4 end_of_line = crlf dotnet_style_collection_initializer = true:suggestion dotnet_style_prefer_simplified_boolean_expressions = true:suggestion @@ -351,13 +255,10 @@ dotnet_style_prefer_inferred_tuple_names = true:suggestion dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion dotnet_style_prefer_compound_assignment = true:suggestion dotnet_style_prefer_simplified_interpolation = true:suggestion -dotnet_style_namespace_match_folder = true:suggestion dotnet_style_readonly_field = true:suggestion dotnet_style_predefined_type_for_locals_parameters_members = true:silent dotnet_style_predefined_type_for_member_access = true:silent dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent -dotnet_style_allow_multiple_blank_lines_experimental = true:silent -dotnet_style_allow_statement_immediately_after_block_experimental = true:silent dotnet_code_quality_unused_parameters = all:suggestion dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent diff --git a/EHR.csproj b/EHR.csproj index fa37a85ec..c13b8ffee 100644 --- a/EHR.csproj +++ b/EHR.csproj @@ -37,7 +37,7 @@ - + diff --git a/EHR.sln.DotSettings b/EHR.sln.DotSettings index 8784b5d37..4f43706a5 100644 --- a/EHR.sln.DotSettings +++ b/EHR.sln.DotSettings @@ -1,6 +1,12 @@  SOLUTION SUGGESTION + WARNING + HINT + True + + WARNING + BaseClass False 0 @@ -66,6 +72,7 @@ True <Policy><Descriptor Staticness="Any" AccessRightKinds="Any" Description="Parameters"><ElementKinds><Kind Name="PARAMETER" /></ElementKinds></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="aaBb"><ExtraRule Prefix="__" Suffix="" Style="aaBb" /></Policy></Policy> + <Policy><Descriptor Staticness="Any" AccessRightKinds="Public" Description="Harmony Special Parameter Name"><ElementKinds><Kind Name="PARAMETER" /></ElementKinds></Descriptor><Policy Inspect="True" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="aaBb"><ExtraRule Prefix="__" Suffix="" Style="aaBb" /></Policy></Policy> False False True diff --git a/Gamemodes/StopAndGo.cs b/Gamemodes/StopAndGo.cs index efb186636..dd33bf2bb 100644 --- a/Gamemodes/StopAndGo.cs +++ b/Gamemodes/StopAndGo.cs @@ -8,19 +8,19 @@ using static EHR.Translator; namespace EHR.Gamemodes; -public class Counter(int totalGreenTime, int totalRedTime, long startTimeStamp, char symbol, bool isRed, Func randomRedTimeFunc, Func randomGreenTimeFunc, bool isYellow = false) +public class Counter(int totalGreenTime, int totalRedTime, char symbol, bool isRed, Func randomRedTimeFunc, Func randomGreenTimeFunc, bool isYellow = false) { private int TotalGreenTime { get; set; } = totalGreenTime; public int TotalRedTime { get; private set; } = totalRedTime; - public long StartTimeStamp { get; set; } = startTimeStamp; + public Stopwatch Stopwatch { get; } = Stopwatch.StartNew(); private char Symbol { get; } = symbol; public bool IsRed { get; private set; } = isRed; private Func RandomRedTime { get; } = randomRedTimeFunc; private Func RandomGreenTime { get; } = randomGreenTimeFunc; private bool IsYellow { get; set; } = isYellow; - private static int TotalYellowTime => 3; + private const int TotalYellowTime = 3; - public int Timer => (IsRed ? TotalRedTime : IsYellow ? TotalYellowTime : TotalGreenTime) - (int)Math.Round((double)(Utils.TimeStamp - StartTimeStamp)); + public int Timer => (IsRed ? TotalRedTime : IsYellow ? TotalYellowTime : TotalGreenTime) - (int)Stopwatch.Elapsed.TotalSeconds; public string ColoredTimerString { @@ -45,26 +45,26 @@ public class Counter(int totalGreenTime, int totalRedTime, long startTimeStamp, { if (Timer <= 0) { - switch (IsRed) + switch (IsRed, IsYellow) { // Change from green to yellow - case false when !IsYellow: + case (IsRed: false, IsYellow: false): IsYellow = true; break; // Change from red to green - case true when !IsYellow: + case (IsRed: true, IsYellow: false): TotalGreenTime = RandomGreenTime(Symbol); IsRed = false; break; // Change from yellow to red - case false when IsYellow: + case (IsRed: false, IsYellow: true): TotalRedTime = RandomRedTime(Symbol); IsYellow = false; IsRed = true; break; } - StartTimeStamp = Utils.TimeStamp; + Stopwatch.Restart(); } } } @@ -347,7 +347,6 @@ internal static class StopAndGo { if (Options.CurrentGameMode != CustomGameMode.StopAndGo) return; - FixedUpdatePatch.LastSuffix = []; FixedUpdatePatch.Limit = []; AllPlayerTimers = []; RoundTimer = Stopwatch.StartNew(); @@ -360,14 +359,12 @@ internal static class StopAndGo RoundTimer = Stopwatch.StartNew(); FixedUpdatePatch.DoChecks = true; - long now = Utils.TimeStamp; - foreach (PlayerControl pc in Main.EnumerateAlivePlayerControls()) { int startingGreenTime = StartingGreenTime(pc); Vector2 pos = pc.Pos(); - Counter[] counters = new[] { '⬅', '⇅', '➡' }.Select(x => new Counter(startingGreenTime, RandomRedTime(x), now, x, false, RandomRedTime, RandomGreenTime)).ToArray(); + Counter[] counters = new[] { '⬅', '⇅', '➡' }.Select(x => new Counter(startingGreenTime, RandomRedTime(x), x, false, RandomRedTime, RandomGreenTime)).ToArray(); AllPlayerTimers[pc.PlayerId] = new(counters, pos.x, pos.y, PlayerLives.GetInt()); float limit; @@ -402,7 +399,7 @@ internal static class StopAndGo if (!pc.IsAlive() || !AllPlayerTimers.TryGetValue(pc.PlayerId, out StopAndGoPlayerData timers)) return string.Empty; string text = IsEventActive ? $"{string.Format(GetString("StopAndGo_EventActive"), GetString($"StopAndGo_Event_{Event.Type}"), Event.Duration + Event.StartTimeStamp - Utils.TimeStamp)}\n" : "\n"; - text += IsEventActive && Event.Type == Events.FrozenTimers ? FixedUpdatePatch.LastSuffix[pc.PlayerId].Trim() : timers.ToString(); + text += timers.ToString(); if (TimeSinceStart < 20 && EnableTutorial.GetBool() && !HasPlayed.Contains(pc.FriendCode)) text += $"\n\n{GetString("StopAndGo_Tutorial")}"; @@ -420,7 +417,6 @@ internal static class StopAndGo { public static bool DoChecks; private static long LastFixedUpdate; - public static Dictionary LastSuffix = []; public static Dictionary Limit = []; public static void Postfix(PlayerControl __instance) @@ -480,7 +476,8 @@ internal static class StopAndGo } case Events.FrozenTimers: { - AllPlayerTimers.Values.SelectMany(x => new[] { x.LeftCounter, x.MiddleCounter, x.RightCounter }).Do(x => x.StartTimeStamp += duration); + AllPlayerTimers.Values.SelectMany(x => new[] { x.LeftCounter, x.MiddleCounter, x.RightCounter }).Do(x => x.Stopwatch.Stop()); + LateTask.New(() => AllPlayerTimers.Values.SelectMany(x => new[] { x.LeftCounter, x.MiddleCounter, x.RightCounter }).Do(x => x.Stopwatch.Start()), duration, log: false); break; } } @@ -564,19 +561,19 @@ internal static class StopAndGo } End: + + if (IsEventActive && Event.Type == Events.FrozenTimers) return; data.UpdateCounters(); - - if (!IsEventActive || Event.Type != Events.FrozenTimers) - LastSuffix[pc.PlayerId] = GetSuffixText(pc); - - bool IsCounterRed(Counter counter) => counter.IsRed && (pc.AmOwner || counter.Timer != counter.TotalRedTime); } if (LastFixedUpdate == now) return; LastFixedUpdate = now; Utils.NotifyRoles(); + return; + + bool IsCounterRed(Counter counter) => counter.IsRed && (pc.AmOwner || counter.Timer != counter.TotalRedTime); } } } diff --git a/Modules/CustomNetObject.cs b/Modules/CustomNetObject.cs index 3d5dbdd79..457cbf81b 100644 --- a/Modules/CustomNetObject.cs +++ b/Modules/CustomNetObject.cs @@ -432,6 +432,11 @@ namespace EHR finally { Gone = true; } } } + + public override void OnMeeting() + { + Despawn(); + } } internal sealed class PlayerDetector : CustomNetObject diff --git a/Modules/CustomSounds.cs b/Modules/CustomSounds.cs index d34513b93..1ee86de50 100644 --- a/Modules/CustomSounds.cs +++ b/Modules/CustomSounds.cs @@ -14,19 +14,15 @@ public static class CustomSoundsManager public static void RPCPlayCustomSound(this PlayerControl pc, string sound, float volume = 1f, float pitch = 1f, bool force = false) { - if (!force) - { - if (!AmongUsClient.Instance.AmHost || !pc.IsModdedClient()) - return; - } + if (!force && (!AmongUsClient.Instance.AmHost || !pc.IsModdedClient())) return; if (pc == null || PlayerControl.LocalPlayer.PlayerId == pc.PlayerId) { - Play(sound); + Play(sound, volume, pitch); return; } - MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.PlayCustomSound, SendOption.Reliable, pc.OwnerId); + MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.PlayCustomSound, SendOption.None, pc.OwnerId); writer.Write(sound); writer.Write(volume); writer.Write(pitch); @@ -37,10 +33,13 @@ public static class CustomSoundsManager { if (!AmongUsClient.Instance.AmHost) return; - MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.PlayCustomSound, SendOption.Reliable); + Play(sound, volume, pitch); + + MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.PlayCustomSound, SendOption.None); writer.Write(sound); + writer.Write(volume); + writer.Write(pitch); AmongUsClient.Instance.FinishRpcImmediately(writer); - Play(sound); } public static void ReceiveRPC(MessageReader reader) diff --git a/Modules/Debugger.cs b/Modules/Debugger.cs index 787a25b49..9c9542e39 100644 --- a/Modules/Debugger.cs +++ b/Modules/Debugger.cs @@ -16,9 +16,11 @@ internal static class Logger { private static bool IsEnable; private static readonly List DisableList = []; +#if DEBUG public static bool IsAlsoInGame; +#endif - private static readonly HashSet NowDetailedErrorLog = []; + private static readonly Dictionary NowDetailedErrorLog = []; public static void Enable() { @@ -53,7 +55,7 @@ internal static class Logger NotificationPopper np = NotificationPopperPatch.Instance; - if (np != null) + if (np) { Warn(text, "SendInGame"); @@ -72,26 +74,31 @@ internal static class Logger { if (!IsEnable || DisableList.Contains(tag) || (level == LogLevel.Debug && !DebugModeManager.AmDebugger)) return; +#if DEBUG if (IsAlsoInGame) SendInGame($"[{tag}]{text}"); +#endif string logText; - if (level is LogLevel.Error or LogLevel.Fatal && !multiLine && !NowDetailedErrorLog.Contains(tag)) + DateTime now = DateTime.Now; + + if (level is LogLevel.Error or LogLevel.Fatal && !multiLine && (!NowDetailedErrorLog.TryGetValue(tag, out DateTime dt) || dt.AddSeconds(3) < now)) { - var t = DateTime.Now.ToString("HH:mm:ss"); + var t = now.ToString("HH:mm:ss"); StackFrame stack = new(2); string className = stack.GetMethod()?.ReflectedType?.Name; string memberName = stack.GetMethod()?.Name; logText = $"[{t}][{className}.{memberName}({Path.GetFileName(fileName)}:{lineNumber})][{tag}]{text}"; - NowDetailedErrorLog.Add(tag); - LateTask.New(() => NowDetailedErrorLog.Remove(tag), 3f, log: false); + NowDetailedErrorLog[tag] = now; } else { if (escapeCRLF) text = text.Replace("\r", "\\r").Replace("\n", "\\n"); - var t = DateTime.Now.ToString("HH:mm:ss"); + var t = now.ToString("HH:mm:ss"); logText = $"[{t}][{tag}]{text}"; + + if (level == LogLevel.Message) NowDetailedErrorLog.Clear(); } CustomLogger.Instance.Log(level.ToString(), logText, multiLine); diff --git a/Modules/EmbeddedDeps.cs b/Modules/EmbeddedDeps.cs index 5101c951a..fda3cf2f7 100644 --- a/Modules/EmbeddedDeps.cs +++ b/Modules/EmbeddedDeps.cs @@ -1,4 +1,4 @@ -#nullable enable +/*#nullable enable using System; using System.IO; using System.Linq; @@ -47,3 +47,4 @@ internal static class EmbeddedDeps return loaded; } } +*/ \ No newline at end of file diff --git a/Modules/ErrorText.cs b/Modules/ErrorText.cs index 8d0b0cf86..24659ad86 100644 --- a/Modules/ErrorText.cs +++ b/Modules/ErrorText.cs @@ -168,7 +168,7 @@ public class ErrorText : MonoBehaviour Frame = 0; - if (_camera != null && _camera1 != null) return; + if (_camera && _camera1) return; try { diff --git a/Modules/FixedUpdateCaller.cs b/Modules/FixedUpdateCaller.cs index 08f2c25b4..b9265dfe2 100644 --- a/Modules/FixedUpdateCaller.cs +++ b/Modules/FixedUpdateCaller.cs @@ -3,7 +3,6 @@ using System.Linq; using EHR.Gamemodes; using EHR.Patches; using HarmonyLib; -using Hazel; using InnerNet; namespace EHR.Modules; @@ -111,7 +110,7 @@ public static class FixedUpdateCaller NonLowLoadPlayerIndex = Math.Min(0, -(30 - count)); CustomGameMode currentGameMode = Options.CurrentGameMode; - bool vanilla = GameStates.CurrentServerType == GameStates.ServerType.Vanilla; + //bool vanilla = GameStates.CurrentServerType == GameStates.ServerType.Vanilla; for (var index = 0; index < count; index++) { @@ -125,8 +124,8 @@ public static class FixedUpdateCaller if (lobby) continue; - if (vanilla && NonLowLoadPlayerIndex == index) - Utils.NotifyRoles(SpecifySeer: pc, ForceLoop: true, SendOption: SendOption.None); + // if (vanilla && NonLowLoadPlayerIndex == index) + // Utils.NotifyRoles(SpecifySeer: pc, ForceLoop: true, SendOption: Hazel.SendOption.None); switch (currentGameMode) { diff --git a/Modules/GameOptionsSender/GameOptionsSender.cs b/Modules/GameOptionsSender/GameOptionsSender.cs index 0147622cb..3bdd8c7b8 100644 --- a/Modules/GameOptionsSender/GameOptionsSender.cs +++ b/Modules/GameOptionsSender/GameOptionsSender.cs @@ -119,32 +119,38 @@ public abstract class GameOptionsSender public static IEnumerator SendDirtyGameOptionsContinuously() { - while (GameStates.InGame || GameStates.IsLobby) + try { - for (var index = 0; index < AllSenders.Count; index++) + while (GameStates.InGame || GameStates.IsLobby) { - GameOptionsSender sender = AllSenders[index]; - - yield return WaitFrameIfNecessary(); - - if (sender == null || !sender.AmValid()) + for (var index = 0; index < AllSenders.Count; index++) { - AllSenders.RemoveAt(index); - index--; - continue; + yield return WaitFrameIfNecessary(); + + if (index >= AllSenders.Count) break; + GameOptionsSender sender = AllSenders[index]; + + if (sender == null || !sender.AmValid()) + { + AllSenders.RemoveAt(index); + index--; + continue; + } + + if (sender.IsDirty) + yield return sender.SendGameOptionsAsync(); + + sender.IsDirty = false; } - if (sender.IsDirty) - yield return sender.SendGameOptionsAsync(); - - sender.IsDirty = false; + ForceWaitFrame = true; + yield return WaitFrameIfNecessary(); } - - ForceWaitFrame = true; - yield return WaitFrameIfNecessary(); } - - ActiveCoroutine = null; + finally + { + ActiveCoroutine = null; + } } protected static IEnumerator WaitFrameIfNecessary() diff --git a/Modules/GameOptionsSender/PlayerGameOptionsSender.cs b/Modules/GameOptionsSender/PlayerGameOptionsSender.cs index 27f8bab56..797792e7b 100644 --- a/Modules/GameOptionsSender/PlayerGameOptionsSender.cs +++ b/Modules/GameOptionsSender/PlayerGameOptionsSender.cs @@ -687,7 +687,7 @@ public sealed class PlayerGameOptionsSender(PlayerControl player) : GameOptionsS protected override bool AmValid() { - return base.AmValid() && player != null && player.Data != null && !player.Data.Disconnected && Main.RealOptionsData != null; + return base.AmValid() && player && player.Data && !player.Data.Disconnected && Main.RealOptionsData != null; } } diff --git a/Modules/RPC.cs b/Modules/RPC.cs index 9a4138759..7369fef22 100644 --- a/Modules/RPC.cs +++ b/Modules/RPC.cs @@ -467,8 +467,8 @@ internal static class RPCHandlerPatch try { - if (option.Id == OptionItem.PresetId && option.CurrentValue != 9) - option.SetValue(9, false, false); + if (option.Id == OptionItem.PresetId && option.CurrentValue != 19) + option.SetValue(19, false, false); } catch (Exception e) { Utils.ThrowException(e); } } diff --git a/Modules/Utils.cs b/Modules/Utils.cs index 6c4710804..26534583b 100644 --- a/Modules/Utils.cs +++ b/Modules/Utils.cs @@ -15,7 +15,6 @@ using AmongUs.InnerNet.GameDataMessages; using BepInEx; using EHR.Gamemodes; using EHR.Modules; -using EHR.Modules.Extensions; using EHR.Patches; using EHR.Roles; using HarmonyLib; @@ -1723,9 +1722,12 @@ public static class Utils { try { - if (Options.CurrentGameMode != CustomGameMode.Standard || !deadPlayer || deadPlayer.Object.Is(CustomRoles.Renegade) || Main.HasJustStarted || !GameStates.InGame || !Options.SpawnAdditionalRenegadeOnImpsDead.GetBool() || Main.AllAlivePlayerControls.Count < Options.SpawnAdditionalRenegadeMinAlivePlayers.GetInt() || CustomRoles.Renegade.RoleExist(true) || Main.EnumerateAlivePlayerControls().Any(x => x.PlayerId != deadPlayer.PlayerId && (x.Is(CustomRoleTypes.Impostor) || (x.IsNeutralKiller() && !Options.SpawnAdditionalRenegadeWhenNKAlive.GetBool())))) return; + if (Options.CurrentGameMode != CustomGameMode.Standard || !deadPlayer || deadPlayer.Object.Is(CustomRoles.Renegade) || Main.HasJustStarted || !GameStates.InGame || !Options.SpawnAdditionalRenegadeOnImpsDead.GetBool()) return; - PlayerControl[] listToChooseFrom = Main.EnumerateAlivePlayerControls().Where(x => x.PlayerId != deadPlayer.PlayerId && x.Is(CustomRoleTypes.Crewmate) && !x.Is(CustomRoles.Loyal)).ToArray(); + var aapc = Main.AllAlivePlayerControls; + if (aapc.Count < Options.SpawnAdditionalRenegadeMinAlivePlayers.GetInt() || aapc.Any(x => x.Is(CustomRoles.Renegade) || (x.PlayerId != deadPlayer.PlayerId && (x.Is(CustomRoleTypes.Impostor) || (x.IsNeutralKiller() && !Options.SpawnAdditionalRenegadeWhenNKAlive.GetBool()))))) return; + + PlayerControl[] listToChooseFrom = aapc.Where(x => x.PlayerId != deadPlayer.PlayerId && x.Is(CustomRoleTypes.Crewmate) && !x.Is(CustomRoles.Loyal)).ToArray(); if (listToChooseFrom.Length > 0) { @@ -1745,7 +1747,7 @@ public static class Utils IEnumerator WaitForMeetingEnd() { while (AntiBlackout.SkipTasks || GameStates.IsMeeting || ExileController.Instance) yield return null; - if (GameStates.IsEnded || GameStates.IsLobby) yield break; + if (GameStates.IsEnded || GameStates.IsLobby || !pc) yield break; pc.RpcChangeRoleBasis(CustomRoles.Renegade); pc.ResetKillCooldown(); pc.SetKillCooldown(); @@ -1823,8 +1825,8 @@ public static class Utils if (vanilla) { - if (importance != MessageImportance.High && GameStates.InGame && !title.Contains("#ffff00") && !title.Contains('⚠') && !text.Contains('⚠') && title != GetString("NoSpamAnymoreUseCmd")) - sendOption = SendOption.None; + // if (importance != MessageImportance.High && GameStates.InGame && !title.Contains("#ffff00") && !title.Contains('⚠') && !text.Contains('⚠') && title != GetString("NoSpamAnymoreUseCmd")) + // sendOption = SendOption.None; text = ReplaceHexColorsWithSafeColors(text); text = ReplaceDigitsOutsideRichText(text); @@ -2645,7 +2647,7 @@ public static class Utils { try { - if (!ForMeeting && !NoCache && !ForceLoop && !CamouflageIsForMeeting && !GuesserIsForMeeting && !MushroomMixup && GameStates.CurrentServerType == GameStates.ServerType.Vanilla) return; + //if (!ForMeeting && !NoCache && !ForceLoop && !CamouflageIsForMeeting && !GuesserIsForMeeting && !MushroomMixup && GameStates.CurrentServerType == GameStates.ServerType.Vanilla) return; if (!AmongUsClient.Instance.AmHost) return; if (!SetUpRoleTextPatch.IsInIntro && ((SpecifySeer && SpecifySeer.IsModdedClient() && (Options.CurrentGameMode == CustomGameMode.Standard || SpecifySeer.IsHost())) || (GameStates.IsMeeting && !ForMeeting) || GameStates.IsLobby)) return; diff --git a/Modules/Zoom.cs b/Modules/Zoom.cs index d8869cc12..693900523 100644 --- a/Modules/Zoom.cs +++ b/Modules/Zoom.cs @@ -10,16 +10,18 @@ namespace EHR; public static class Zoom { private static bool ResetButtons; + private static Camera Main; public static void Postfix() { try { - if (!Camera.main) return; + if (!Main) Main = Camera.main; + if (!Main) return; if (((GameStates.IsShip && !GameStates.IsMeeting && GameStates.IsCanMove && !PlayerControl.LocalPlayer.IsAlive()) || (GameStates.IsLobby && GameStates.IsCanMove)) && !InGameRoleInfoMenu.Showing) { - if (Camera.main.orthographicSize > 3.0f) ResetButtons = true; + if (Main.orthographicSize > 3.0f) ResetButtons = true; if (Input.touchSupported) { @@ -39,7 +41,7 @@ public static class Zoom { case > 0: { - if (Camera.main.orthographicSize > 3.0f) + if (Main.orthographicSize > 3.0f) SetZoomSize(); break; @@ -48,7 +50,7 @@ public static class Zoom { if (GameStates.IsDead || GameStates.IsFreePlay || DebugModeManager.AmDebugger || GameStates.IsLobby) { - if (Camera.main.orthographicSize < 18.0f) + if (Main.orthographicSize < 18.0f) SetZoomSize(true); } @@ -62,7 +64,7 @@ public static class Zoom { case > 0: { - if (Camera.main.orthographicSize > 3.0f) + if (Main.orthographicSize > 3.0f) SetZoomSize(); break; @@ -71,7 +73,7 @@ public static class Zoom { if (GameStates.IsDead || GameStates.IsFreePlay || DebugModeManager.AmDebugger || GameStates.IsLobby) { - if (Camera.main.orthographicSize < 18.0f) + if (Main.orthographicSize < 18.0f) SetZoomSize(true); } @@ -88,25 +90,25 @@ public static class Zoom public static void SetZoomSize(bool times = false, bool reset = false) { - if (!Camera.main || !HudManager.InstanceExists) return; + if (!Main || !HudManager.InstanceExists) return; var size = 1.5f; if (!times) size = 1 / size; if (reset) { - Camera.main.orthographicSize = 3.0f; + Main.orthographicSize = 3.0f; HudManager.Instance.UICamera.orthographicSize = 3.0f; HudManager.Instance.Chat.transform.localScale = Vector3.one; if (GameStates.IsMeeting) MeetingHud.Instance.transform.localScale = Vector3.one; } else { - Camera.main.orthographicSize *= size; + Main.orthographicSize *= size; HudManager.Instance.UICamera.orthographicSize *= size; } - HudManager.Instance?.ShadowQuad?.gameObject.SetActive((reset || Mathf.Approximately(Camera.main.orthographicSize, 3.0f)) && PlayerControl.LocalPlayer.IsAlive()); + HudManager.Instance?.ShadowQuad?.gameObject.SetActive((reset || Mathf.Approximately(Main.orthographicSize, 3.0f)) && PlayerControl.LocalPlayer.IsAlive()); if (ResetButtons) { @@ -117,9 +119,9 @@ public static class Zoom public static void OnFixedUpdate() { - if (!Camera.main || !HudManager.InstanceExists) return; + if (!Main || !HudManager.InstanceExists) return; - HudManager.Instance?.ShadowQuad?.gameObject.SetActive(Mathf.Approximately(Camera.main.orthographicSize, 3.0f) && PlayerControl.LocalPlayer.IsAlive()); + HudManager.Instance?.ShadowQuad?.gameObject.SetActive(Mathf.Approximately(Main.orthographicSize, 3.0f) && PlayerControl.LocalPlayer.IsAlive()); } } diff --git a/Patches/ChatCommandPatch.cs b/Patches/ChatCommandPatch.cs index 45d026f09..dc3d99117 100644 --- a/Patches/ChatCommandPatch.cs +++ b/Patches/ChatCommandPatch.cs @@ -782,7 +782,7 @@ internal static class ChatCommands private static void CopyPresetCommand(PlayerControl player, string text, string[] args) { - if (args.Length < 3 || !int.TryParse(args[1], out int sourcePresetId) || sourcePresetId is < 1 or > 10 || (!int.TryParse(args[2], out int targetPreset) && targetPreset is < 1 or > 10)) return; + if (args.Length < 3 || !int.TryParse(args[1], out int sourcePresetId) || sourcePresetId is < 1 or > 20 || (!int.TryParse(args[2], out int targetPreset) && targetPreset is < 1 or > 20)) return; Prompt.Show(string.Format(GetString("Promt.CopyPreset"), sourcePresetId, targetPreset), Copy, () => { }); return; diff --git a/Patches/CheckGameEndPatch.cs b/Patches/CheckGameEndPatch.cs index c95ee6989..c92172522 100644 --- a/Patches/CheckGameEndPatch.cs +++ b/Patches/CheckGameEndPatch.cs @@ -330,14 +330,14 @@ internal static class GameEndChecker WinnerIds.UnionWith(Main.LoversPlayers.Select(x => x.PlayerId)); } - if (Options.NeutralWinTogether.GetBool() && (WinnerRoles.Any(x => x.IsNeutral()) || WinnerIds.Select(x => GetPlayerById(x)).Any(x => x != null && x.GetCustomRole().IsNeutral() && !x.IsMadmate()))) + if (Options.NeutralWinTogether.GetBool() && (WinnerRoles.Any(x => x.IsNeutral()) || WinnerIds.Select(x => GetPlayerById(x)).Any(x => x && x.GetCustomRole().IsNeutral() && !x.IsMadmate()))) WinnerIds.UnionWith(Main.EnumeratePlayerControls().Where(x => x.GetCustomRole().IsNeutral()).Select(x => x.PlayerId)); else if (Options.NeutralRoleWinTogether.GetBool()) { foreach (byte id in WinnerIds.ToArray()) { PlayerControl pc = GetPlayerById(id); - if (pc == null || !pc.GetCustomRole().IsNeutral()) continue; + if (!pc || !pc.GetCustomRole().IsNeutral()) continue; foreach (PlayerControl tar in Main.EnumeratePlayerControls()) { @@ -834,7 +834,7 @@ internal static class GameEndChecker IEnumerable> teams = FreeForAll.PlayerTeams.GroupBy(x => x.Value, x => x.Key).Select(x => x.Where(p => { PlayerControl pc = GetPlayerById(p); - return pc != null && !pc.Data.Disconnected; + return pc && !pc.Data.Disconnected; }).ToHashSet()).Where(x => x.Count > 0); foreach (HashSet team in teams) @@ -893,7 +893,7 @@ internal static class GameEndChecker if (StopAndGo.RoundTime <= 0 || !StopAndGo.RoundTimer.IsRunning) { var apc = Main.AllPlayerControls; - SetWinner(Main.GM.Value && apc.Count == 1 ? PlayerControl.LocalPlayer : apc.Where(x => !x.Is(CustomRoles.GM) && x != null).OrderBy(x => StopAndGo.GetRankFromScore(x.PlayerId)).ThenByDescending(x => x.IsAlive()).First()); + SetWinner(Main.GM.Value && apc.Count == 1 ? PlayerControl.LocalPlayer : apc.Where(x => x && !x.Is(CustomRoles.GM)).OrderBy(x => StopAndGo.GetRankFromScore(x.PlayerId)).ThenByDescending(x => x.IsAlive()).First()); return true; } diff --git a/Patches/ClientPatch.cs b/Patches/ClientPatch.cs index 3bcce0fbe..f1afb619c 100644 --- a/Patches/ClientPatch.cs +++ b/Patches/ClientPatch.cs @@ -31,6 +31,15 @@ internal static class MakePublicPatch } }*/ +[HarmonyPatch(typeof(InnerNetClient), nameof(InnerNetClient.StartRpcImmediately))] +static class StartRpcImmediatelyPatch +{ + public static void Postfix(uint targetNetId, byte callId, Hazel.SendOption option, int targetClientId = -1) + { + Logger.Info($"Starting RPC: {callId} ({RPC.GetRpcName(callId)}) as {targetNetId} with SendOption {option} to {targetClientId}", "StartRpcImmediately"); + } +} + [HarmonyPatch(typeof(MMOnlineManager), nameof(MMOnlineManager.Start))] // ReSharper disable once InconsistentNaming internal static class MMOnlineManagerStartPatch @@ -130,7 +139,7 @@ internal static class SetResolutionManager { public static void Postfix() { - if (MainMenuManagerPatch.UpdateButton != null) + if (MainMenuManagerPatch.UpdateButton) MainMenuManagerPatch.UpdateButton.transform.localPosition = MainMenuManagerPatch.Template.transform.localPosition + new Vector3(0.25f, 0.75f); } } @@ -138,16 +147,9 @@ internal static class SetResolutionManager [HarmonyPatch(typeof(InnerNetClient), nameof(InnerNetClient.SendAllStreamedObjects))] internal static class InnerNetObjectSerializePatch { - private static int Count; - public static void Prefix() { - if (!AmongUsClient.Instance.AmHost) return; - - if (Count++ < 100) return; - Count = 0; - - if (GameOptionsSender.ActiveCoroutine != null) return; + if (!AmongUsClient.Instance.AmHost || GameOptionsSender.ActiveCoroutine != null) return; GameOptionsSender.ActiveCoroutine = Main.Instance.StartCoroutine(GameOptionsSender.SendDirtyGameOptionsContinuously()); } } diff --git a/Patches/ControlPatch.cs b/Patches/ControlPatch.cs index 45b3c9714..b4d91fd88 100644 --- a/Patches/ControlPatch.cs +++ b/Patches/ControlPatch.cs @@ -219,15 +219,15 @@ internal static class ControllerManagerUpdatePatch Utils.SendMessage(GetString("HostKillSelfByCommand"), title: $"{GetString("DefaultSystemMessageTitle")}"); } + if (!Options.NoGameEnd.GetBool()) return; + +#if DEBUG if (KeysDown(KeyCode.F2, KeyCode.LeftControl)) { Logger.IsAlsoInGame = !Logger.IsAlsoInGame; Logger.SendInGame($"In-game output log: {Logger.IsAlsoInGame}"); } - if (!Options.NoGameEnd.GetBool()) return; - -#if DEBUG if (KeysDown(KeyCode.Return, KeyCode.F, KeyCode.LeftShift)) { Utils.FlashColor(new(1f, 0f, 0f, 0.3f)); diff --git a/Patches/CredentialsPatch.cs b/Patches/CredentialsPatch.cs index 239848174..23dab66e2 100644 --- a/Patches/CredentialsPatch.cs +++ b/Patches/CredentialsPatch.cs @@ -466,25 +466,23 @@ internal static class TitleLogoPatch [HarmonyPatch(typeof(ModManager), nameof(ModManager.LateUpdate))] internal static class ModManagerLateUpdatePatch { + + public static bool Prefix(ModManager __instance) { __instance.ShowModStamp(); ChatBubbleShower.Update(); - if (LobbySharingAPI.LastRoomCode != string.Empty && Utils.TimeStamp - LobbySharingAPI.LastRequestTimeStamp > Options.LobbyUpdateInterval.GetInt()) - LobbySharingAPI.NotifyLobbyStatusChanged(PlayerControl.LocalPlayer == null ? LobbyStatus.Closed : GameStates.InGame ? LobbyStatus.In_Game : LobbyStatus.In_Lobby); + if (!string.IsNullOrEmpty(LobbySharingAPI.LastRoomCode) && Utils.TimeStamp - LobbySharingAPI.LastRequestTimeStamp > Options.LobbyUpdateInterval.GetInt()) + LobbySharingAPI.NotifyLobbyStatusChanged(!PlayerControl.LocalPlayer ? LobbyStatus.Closed : GameStates.InGame ? LobbyStatus.In_Game : LobbyStatus.In_Lobby); return false; } public static void Postfix(ModManager __instance) { - __instance.localCamera = !HudManager.InstanceExists - ? Camera.main - : HudManager.Instance.GetComponentInChildren(); - - if (__instance.localCamera != null) + if (__instance.localCamera) { float offsetY = HudManager.InstanceExists ? 1.1f : 0.9f; @@ -492,6 +490,12 @@ internal static class ModManagerLateUpdatePatch __instance.localCamera, AspectPosition.EdgeAlignments.RightTop, new(0.4f, offsetY, __instance.localCamera.nearClipPlane + 0.1f)); } + else + { + __instance.localCamera = !HudManager.InstanceExists + ? Camera.main + : HudManager.Instance.GetComponentInChildren(); + } } } diff --git a/Patches/GameOptionsMenuPatch.cs b/Patches/GameOptionsMenuPatch.cs index 32eb976d6..dd3c668fa 100644 --- a/Patches/GameOptionsMenuPatch.cs +++ b/Patches/GameOptionsMenuPatch.cs @@ -1,17 +1,16 @@ using System; using System.Collections; -using System.Collections.Generic; -using System.Diagnostics; using System.Linq; using BepInEx.Unity.IL2CPP.Utils.Collections; -using EHR.Gamemodes; using EHR.Modules; using EHR.Patches; -using EHR.Roles; using HarmonyLib; +using Il2CppSystem.Collections.Generic; using TMPro; using UnityEngine; using UnityEngine.Events; +using EHR.Roles; +using EHR.Gamemodes; // ReSharper disable PossibleLossOfFraction @@ -21,30 +20,9 @@ namespace EHR; public static class ModGameOptionsMenu { public static int TabIndex; - private static Dictionary _optionList; - private static Dictionary _behaviourList; - private static Dictionary _categoryHeaderList; - - public static void ClearDictionaries() - { - OptionList.Clear(); - BehaviourList.Clear(); - CategoryHeaderList.Clear(); - } - - public static OptionItem GetFromBehaviour(OptionBehaviour behaviour) - { - if (OptionList.TryGetValue(behaviour.GetHashCode(), out int id)) - { - return OptionItem.FastOptions[id]; - } - - return null;// behaviour.GetComponent() is { item: var item } ? item : null; - } - - public static Dictionary OptionList => _optionList ??= new(); - public static Dictionary BehaviourList => _behaviourList ??= new(); - public static Dictionary CategoryHeaderList => _categoryHeaderList ??= new(); + public static Dictionary OptionList = new(); + public static Dictionary BehaviourList = new(); + public static Dictionary CategoryHeaderList = new(); } [HarmonyPatch(typeof(GameOptionsMenu))] @@ -133,102 +111,90 @@ public static class GameOptionsMenuPatch const float posZ = -2.0f; TextOptionItem header = null; - - const int frameBudget = 10; // milliseconds - var stopwatch = new Stopwatch(); - stopwatch.Start(); - - foreach (var option in OptionItem.AllOptions) + + for (var index = 0; index < OptionItem.AllOptions.Count; index++) { + OptionItem option = OptionItem.AllOptions[index]; + if (option.Tab != modTab) continue; + + bool enabled = !option.IsCurrentlyHidden() && AllParentsEnabledAndVisible(option.Parent); + + if (option is TextOptionItem toi) + { + CategoryHeaderMasked categoryHeaderMasked = Object.Instantiate(__instance.categoryHeaderOrigin, Vector3.zero, Quaternion.identity, __instance.settingsContainer); + categoryHeaderMasked.SetHeader(StringNames.RolesCategory, 20); + categoryHeaderMasked.Title.text = option.GetName(disableColor: true).Trim('★', ' '); + categoryHeaderMasked.Background.color = categoryHeaderMasked.Divider.color = option.NameColor; + categoryHeaderMasked.transform.localScale = Vector3.one * 0.63f; + categoryHeaderMasked.transform.localPosition = new(-0.903f, num, posZ); + var chmText = categoryHeaderMasked.transform.FindChild("HeaderText").GetComponent(); + chmText.fontStyle = FontStyles.Bold | FontStyles.SmallCaps; + chmText.fontWeight = FontWeight.Black; + chmText.outlineWidth = 0.17f; + var chmCollider = categoryHeaderMasked.gameObject.AddComponent(); + chmCollider.size = new Vector2(7, 0.7f); + chmCollider.offset = new Vector2(1.5f, -0.3f); + var chmButton = categoryHeaderMasked.gameObject.AddComponent(); + chmButton.ClickSound = __instance.BackButton.GetComponent().ClickSound; + chmButton.OnMouseOver = new(); + chmButton.OnMouseOut = new(); + chmButton.OnClick.AddListener((UnityAction)(() => + { + toi.CollapsesSection = !toi.CollapsesSection; + ReCreateSettings(__instance); + })); + chmButton.SetButtonEnableState(true); + categoryHeaderMasked.gameObject.SetActive(enabled); + ModGameOptionsMenu.CategoryHeaderList.TryAdd(index, categoryHeaderMasked); + + if (enabled) num -= 0.63f; + header = toi; + continue; + } + + option.Header = header; + + if (option.IsHeader && enabled) + num -= 0.18f; + + BaseGameSetting baseGameSetting = GetSetting(option); + if (baseGameSetting == null) continue; + + + OptionBehaviour optionBehaviour; + try { - if (option.Tab != modTab) continue; - - bool enabled = !option.IsCurrentlyHidden() && AllParentsEnabledAndVisible(option.Parent); - - if (option is TextOptionItem toi) + optionBehaviour = baseGameSetting.Type switch { - CategoryHeaderMasked categoryHeaderMasked = Object.Instantiate(__instance.categoryHeaderOrigin, Vector3.zero, Quaternion.identity, __instance.settingsContainer); - categoryHeaderMasked.SetHeader(StringNames.RolesCategory, 20); - categoryHeaderMasked.Title.text = option.GetName(disableColor: true).Trim('★', ' '); - categoryHeaderMasked.Background.color = categoryHeaderMasked.Divider.color = option.NameColor; - categoryHeaderMasked.transform.localScale = Vector3.one * 0.63f; - categoryHeaderMasked.transform.localPosition = new(-0.903f, num, posZ); - var chmText = categoryHeaderMasked.transform.FindChild("HeaderText").GetComponent(); - chmText.fontStyle = FontStyles.Bold | FontStyles.SmallCaps; - chmText.fontWeight = FontWeight.Black; - chmText.outlineWidth = 0.17f; - var chmCollider = categoryHeaderMasked.gameObject.AddComponent(); - chmCollider.size = new Vector2(7, 0.7f); - chmCollider.offset = new Vector2(1.5f, -0.3f); - var chmButton = categoryHeaderMasked.gameObject.AddComponent(); - chmButton.ClickSound = __instance.BackButton.GetComponent().ClickSound; - chmButton.OnMouseOver = new(); - chmButton.OnMouseOut = new(); - chmButton.OnClick.AddListener((UnityAction)(() => - { - toi.CollapsesSection = !toi.CollapsesSection; - ReCreateSettings(__instance); - })); - chmButton.SetButtonEnableState(true); - categoryHeaderMasked.gameObject.SetActive(enabled); - ModGameOptionsMenu.CategoryHeaderList.TryAdd(option.Id, categoryHeaderMasked); - - if (enabled) num -= 0.63f; - header = toi; - continue; - } - - option.Header = header; - - if (option.IsHeader && enabled) - num -= 0.18f; - - BaseGameSetting baseGameSetting = GetSetting(option); - if (baseGameSetting == null) continue; - - - OptionBehaviour optionBehaviour; - - try - { - optionBehaviour = baseGameSetting.Type switch - { - OptionTypes.Checkbox => Object.Instantiate(__instance.checkboxOrigin, Vector3.zero, Quaternion.identity, __instance.settingsContainer), - OptionTypes.String => Object.Instantiate(__instance.stringOptionOrigin, Vector3.zero, Quaternion.identity, __instance.settingsContainer), - OptionTypes.Float or OptionTypes.Int => Object.Instantiate(__instance.numberOptionOrigin, Vector3.zero, Quaternion.identity, __instance.settingsContainer), - _ => throw new Exception("Skipped option type") - }; - } - catch { continue; } - - optionBehaviour.transform.localPosition = new(posX, num, posZ); - OptionBehaviourSetSizeAndPosition(optionBehaviour, option, baseGameSetting.Type); - - if (!ModGameOptionsMenu.OptionList.ContainsValue(option.Id) && option.Name == "Preset") - GameSettingMenuPatch.PresetBehaviour = (NumberOption)optionBehaviour; - - optionBehaviour.transform.localPosition = new(0.952f, num, -2f); - optionBehaviour.SetClickMask(__instance.ButtonClickMask); - optionBehaviour.SetUpFromData(baseGameSetting, 20); - ModGameOptionsMenu.OptionList.TryAdd(optionBehaviour.GetHashCode(), option.Id); - ModGameOptionsMenu.BehaviourList.TryAdd(option.Id, optionBehaviour); - optionBehaviour.gameObject.SetActive(enabled); - optionBehaviour.OnValueChanged = new Action(__instance.ValueChanged); - __instance.Children.Add(optionBehaviour); - - option.OptionBehaviour = optionBehaviour; - - if (enabled) num -= 0.45f; + OptionTypes.Checkbox => Object.Instantiate(__instance.checkboxOrigin, Vector3.zero, Quaternion.identity, __instance.settingsContainer), + OptionTypes.String => Object.Instantiate(__instance.stringOptionOrigin, Vector3.zero, Quaternion.identity, __instance.settingsContainer), + OptionTypes.Float or OptionTypes.Int => Object.Instantiate(__instance.numberOptionOrigin, Vector3.zero, Quaternion.identity, __instance.settingsContainer), + _ => throw new Exception("Skipped option type") + }; } - catch (Exception e) { Utils.ThrowException(e); } + catch { continue; } - if (stopwatch.ElapsedMilliseconds >= frameBudget) - { - stopwatch.Reset(); - yield return null; - stopwatch.Start(); - } + optionBehaviour.transform.localPosition = new(posX, num, posZ); + OptionBehaviourSetSizeAndPosition(optionBehaviour, option, baseGameSetting.Type); + + if (!ModGameOptionsMenu.OptionList.ContainsValue(index) && option.Name == "Preset") + GameSettingMenuPatch.PresetBehaviour = (NumberOption)optionBehaviour; + + optionBehaviour.transform.localPosition = new(0.952f, num, -2f); + optionBehaviour.SetClickMask(__instance.ButtonClickMask); + optionBehaviour.SetUpFromData(baseGameSetting, 20); + ModGameOptionsMenu.OptionList.TryAdd(optionBehaviour, index); + ModGameOptionsMenu.BehaviourList.TryAdd(index, optionBehaviour); + optionBehaviour.gameObject.SetActive(enabled); + optionBehaviour.OnValueChanged = new Action(__instance.ValueChanged); + __instance.Children.Add(optionBehaviour); + + option.OptionBehaviour = optionBehaviour; + + if (enabled) num -= 0.45f; + + if (index % 100 == 0) yield return null; } __instance.ControllerSelectable.Clear(); @@ -355,8 +321,11 @@ public static class GameOptionsMenuPatch { if (ModGameOptionsMenu.TabIndex < 3) return true; - if (ModGameOptionsMenu.GetFromBehaviour(option) is { } item && item.Children.Count > 0) - ReCreateSettings(__instance); + if (ModGameOptionsMenu.OptionList.TryGetValue(option, out int index)) + { + OptionItem item = OptionItem.AllOptions[index]; + if (item != null && item.Children.Count > 0) ReCreateSettings(__instance); + } return false; } @@ -369,13 +338,14 @@ public static class GameOptionsMenuPatch var num = 2.0f; - foreach (var option in OptionItem.AllOptions) + for (var index = 0; index < OptionItem.AllOptions.Count; index++) { + OptionItem option = OptionItem.AllOptions[index]; if (option.Tab != modTab) continue; bool enabled = !option.IsCurrentlyHidden() && AllParentsEnabledAndVisible(option.Parent); - if (ModGameOptionsMenu.CategoryHeaderList.TryGetValue(option.Id, out CategoryHeaderMasked categoryHeaderMasked)) + if (ModGameOptionsMenu.CategoryHeaderList.TryGetValue(index, out CategoryHeaderMasked categoryHeaderMasked)) { categoryHeaderMasked.transform.localPosition = new(-0.903f, num, -2f); categoryHeaderMasked.gameObject.SetActive(enabled); @@ -383,7 +353,7 @@ public static class GameOptionsMenuPatch } else if (option.IsHeader && enabled) num -= 0.18f; - if (ModGameOptionsMenu.BehaviourList.TryGetValue(option.Id, out OptionBehaviour optionBehaviour)) + if (ModGameOptionsMenu.BehaviourList.TryGetValue(index, out OptionBehaviour optionBehaviour)) { optionBehaviour.transform.localPosition = new(0.952f, num, -2f); optionBehaviour.gameObject.SetActive(enabled); @@ -474,17 +444,19 @@ public static class GameOptionsMenuPatch optionsConsole = console; } - if (optionsConsole == null) return; + if (!optionsConsole) return; - if (Camera.main != null) + Camera main = Camera.main; + + if (main) { - GameObject gameObject = Object.Instantiate(optionsConsole.MenuPrefab, Camera.main.transform, false); + GameObject gameObject = Object.Instantiate(optionsConsole.MenuPrefab, main.transform, false); gameObject.transform.localPosition = optionsConsole.CustomPosition; } LateTask.New(() => { - if (GameSettingMenu.Instance == null) return; + if (!GameSettingMenu.Instance) return; GameSettingMenu.Instance.ChangeTab(tab, false); }, 0.01f); @@ -499,28 +471,32 @@ public static class ToggleOptionPatch [HarmonyPrefix] private static bool InitializePrefix(ToggleOption __instance) { - OptionItem item = ModGameOptionsMenu.GetFromBehaviour(__instance); - if (item == null) return true; - - CustomGameMode gm = Options.CurrentGameMode; - Color32 color = gm == CustomGameMode.Standard ? (TabGroup)(ModGameOptionsMenu.TabIndex - 3) switch + if (ModGameOptionsMenu.OptionList.TryGetValue(__instance, out int index)) { - TabGroup.ImpostorRoles => new Color32(255, 25, 25, 255), - TabGroup.CrewmateRoles => new Color32(140, 255, 255, 255), - TabGroup.NeutralRoles => new Color32(255, 171, 27, 255), - TabGroup.CovenRoles => new Color32(123, 63, 187, 255), - _ => new Color32(0, 165, 255, 255) - } : Main.GameModeColors.TryGetValue(gm, out var c) ? c : new Color32(0, 165, 255, 255); - __instance.CheckMark.sprite = Utils.LoadSprite("EHR.Resources.Images.Checkmark.png", 100f); - __instance.CheckMark.color = color; - var renderer = __instance.CheckMark.transform.parent.FindChild("ActiveSprite").GetComponent(); - renderer.sprite = Utils.LoadSprite("EHR.Resources.Images.CheckMarkBox.png", 100f); - renderer.color = color; - - __instance.TitleText.text = item.GetName(); - __instance.CheckMark.enabled = item.GetBool(); - item.OptionBehaviour = __instance; - return false; + OptionItem item = OptionItem.AllOptions[index]; + + CustomGameMode gm = Options.CurrentGameMode; + Color32 color = gm == CustomGameMode.Standard ? (TabGroup)(ModGameOptionsMenu.TabIndex - 3) switch + { + TabGroup.ImpostorRoles => new Color32(255, 25, 25, 255), + TabGroup.CrewmateRoles => new Color32(140, 255, 255, 255), + TabGroup.NeutralRoles => new Color32(255, 171, 27, 255), + TabGroup.CovenRoles => new Color32(123, 63, 187, 255), + _ => new Color32(0, 165, 255, 255) + } : Main.GameModeColors.TryGetValue(gm, out var c) ? c : new Color32(0, 165, 255, 255); + __instance.CheckMark.sprite = Utils.LoadSprite("EHR.Resources.Images.Checkmark.png", 100f); + __instance.CheckMark.color = color; + var renderer = __instance.CheckMark.transform.parent.FindChild("ActiveSprite").GetComponent(); + renderer.sprite = Utils.LoadSprite("EHR.Resources.Images.CheckMarkBox.png", 100f); + renderer.color = color; + + __instance.TitleText.text = item.GetName(); + __instance.CheckMark.enabled = item.GetBool(); + item.OptionBehaviour = __instance; + return false; + } + + return true; } // For some reason, ToggleOption.UpdateValue isn't called for Steam users @@ -528,14 +504,17 @@ public static class ToggleOptionPatch [HarmonyPrefix] private static bool TogglePrefix(ToggleOption __instance) { - OptionItem item = ModGameOptionsMenu.GetFromBehaviour(__instance); - if (item == null) return true; + if (ModGameOptionsMenu.OptionList.TryGetValue(__instance, out int index)) + { + __instance.CheckMark.enabled = !__instance.CheckMark.enabled; + OptionItem item = OptionItem.AllOptions[index]; + item.SetValue(__instance.GetBool() ? 1 : 0); + __instance.OnValueChanged.Invoke(__instance); + NotificationPopperPatch.AddSettingsChangeMessage(item, true); + return false; + } - __instance.CheckMark.enabled = !__instance.CheckMark.enabled; - item.SetValue(__instance.GetBool() ? 1 : 0); - __instance.OnValueChanged.Invoke(__instance); - NotificationPopperPatch.AddSettingsChangeMessage(item, true); - return false; + return true; } } @@ -589,56 +568,65 @@ public static class NumberOptionPatch break; } - OptionItem item = ModGameOptionsMenu.GetFromBehaviour(__instance); - if (item == null) return true; - - __instance.TitleText.text = item.GetName(); - item.OptionBehaviour = __instance; - return false; + if (ModGameOptionsMenu.OptionList.TryGetValue(__instance, out int index)) + { + OptionItem item = OptionItem.AllOptions[index]; + __instance.TitleText.text = item.GetName(); + item.OptionBehaviour = __instance; + return false; + } + + return true; } [HarmonyPatch(nameof(NumberOption.UpdateValue))] [HarmonyPrefix] private static bool UpdateValuePrefix(NumberOption __instance) { - OptionItem item = ModGameOptionsMenu.GetFromBehaviour(__instance); - if (item == null) return true; - - switch (item) + if (ModGameOptionsMenu.OptionList.TryGetValue(__instance, out int index)) { - case IntegerOptionItem integerOptionItem: - integerOptionItem.SetValue(integerOptionItem.Rule.GetNearestIndex(__instance.GetInt())); - break; - case FloatOptionItem floatOptionItem: - floatOptionItem.SetValue(floatOptionItem.Rule.GetNearestIndex(__instance.GetFloat())); - break; - case PresetOptionItem presetOptionItem: - presetOptionItem.SetValue(presetOptionItem.Rule.GetNearestIndex(__instance.GetInt())); - GameOptionsMenuPatch.ReloadUI(); - break; + OptionItem item = OptionItem.AllOptions[index]; + + switch (item) + { + case IntegerOptionItem integerOptionItem: + integerOptionItem.SetValue(integerOptionItem.Rule.GetNearestIndex(__instance.GetInt())); + break; + case FloatOptionItem floatOptionItem: + floatOptionItem.SetValue(floatOptionItem.Rule.GetNearestIndex(__instance.GetFloat())); + break; + case PresetOptionItem presetOptionItem: + presetOptionItem.SetValue(presetOptionItem.Rule.GetNearestIndex(__instance.GetInt())); + GameOptionsMenuPatch.ReloadUI(); + break; + } + + NotificationPopperPatch.AddSettingsChangeMessage(item, true); + return false; } - NotificationPopperPatch.AddSettingsChangeMessage(item, true); - return false; + return true; } [HarmonyPatch(nameof(NumberOption.FixedUpdate))] [HarmonyPrefix] private static bool FixedUpdatePrefix(NumberOption __instance) { - OptionItem item = ModGameOptionsMenu.GetFromBehaviour(__instance); - if (item == null) return true; - - __instance.MinusBtn.SetInteractable(true); - __instance.PlusBtn.SetInteractable(true); - - if (!Mathf.Approximately(__instance.oldValue, __instance.Value)) + if (ModGameOptionsMenu.OptionList.TryGetValue(__instance, out int index)) { - __instance.oldValue = __instance.Value; - __instance.ValueText.text = GetValueString(__instance, __instance.Value, item); + __instance.MinusBtn.SetInteractable(true); + __instance.PlusBtn.SetInteractable(true); + + if (!Mathf.Approximately(__instance.oldValue, __instance.Value)) + { + __instance.oldValue = __instance.Value; + __instance.ValueText.text = GetValueString(__instance, __instance.Value, OptionItem.AllOptions[index]); + } + + return false; } - return false; + return true; } private static string GetValueString(NumberOption __instance, float value, OptionItem item) @@ -708,44 +696,47 @@ public static class StringOptionPatch [HarmonyPrefix] private static bool InitializePrefix(StringOption __instance) { - OptionItem item = ModGameOptionsMenu.GetFromBehaviour(__instance); - if (item == null) return true; - - string name = item.GetName(); - item.OptionBehaviour = __instance; - string name1 = name; - - if (Main.CustomRoleValues.FindFirst(x => Translator.GetString($"{x}") == name1.RemoveHtmlTags(), out CustomRoles role)) + if (ModGameOptionsMenu.OptionList.TryGetValue(__instance, out int index)) { - if (role.ToString().Contains("GuardianAngel")) role = CustomRoles.GA; + OptionItem item = OptionItem.AllOptions[index]; + string name = item.GetName(); + item.OptionBehaviour = __instance; + string name1 = name; - name = name.RemoveHtmlTags(); - - switch (Options.UsePets.GetBool()) + if (Enum.GetValues().FindFirst(x => Translator.GetString($"{x}") == name1.RemoveHtmlTags(), out CustomRoles role)) { - case false when role.OnlySpawnsWithPets(): - name += Translator.GetString("RequiresPetIndicator"); - break; - case true when role.PetActivatedAbility(): - name += Translator.GetString("SupportsPetIndicator"); - break; + if (role.ToString().Contains("GuardianAngel")) role = CustomRoles.GA; + + name = name.RemoveHtmlTags(); + + switch (Options.UsePets.GetBool()) + { + case false when role.OnlySpawnsWithPets(): + name += Translator.GetString("RequiresPetIndicator"); + break; + case true when role.PetActivatedAbility(): + name += Translator.GetString("SupportsPetIndicator"); + break; + } + + if (role.IsExperimental()) name += $"{Translator.GetString("ExperimentalRoleIndicator")}"; + if (role.IsGhostRole()) name += GetGhostRoleTeam(role); + if (role.IsDevFavoriteRole()) name += " <#00ffff>★"; + + __instance.TitleText.fontWeight = FontWeight.Black; + __instance.TitleText.outlineColor = new(255, 255, 255, 255); + __instance.TitleText.outlineWidth = 0.04f; + __instance.LabelBackground.color = Utils.GetRoleColor(role); + __instance.TitleText.color = Color.white; + name = $"{name}"; + SetupHelpIcon(role, __instance); } - if (role.IsExperimental()) name += $"{Translator.GetString("ExperimentalRoleIndicator")}"; - if (role.IsGhostRole()) name += GetGhostRoleTeam(role); - if (role.IsDevFavoriteRole()) name += " <#00ffff>★"; - - __instance.TitleText.fontWeight = FontWeight.Black; - __instance.TitleText.outlineColor = new(255, 255, 255, 255); - __instance.TitleText.outlineWidth = 0.04f; - __instance.LabelBackground.color = Utils.GetRoleColor(role); - __instance.TitleText.color = Color.white; - name = $"{name}"; - SetupHelpIcon(role, __instance); + __instance.TitleText.text = name; + return false; } - __instance.TitleText.text = name; - return false; + return true; } private static void SetupHelpIcon(CustomRoles role, StringOption option) @@ -762,45 +753,46 @@ public static class StringOptionPatch gameOptionButton.OnClick.AddListener((Action)(() => { - var item = ModGameOptionsMenu.GetFromBehaviour(option); - if (item == null) return; - - string name = item.GetName(); - - if (Main.CustomRoleValues.FindFirst(x => Translator.GetString($"{x}") == name.RemoveHtmlTags(), out CustomRoles value)) + if (ModGameOptionsMenu.OptionList.TryGetValue(option, out int index)) { - string roleName = value.IsVanilla() ? value + "EHR" : value.ToString(); - string str = Translator.GetString($"{roleName}InfoLong").FixRoleName(value); - string infoLong; + OptionItem item = OptionItem.AllOptions[index]; + string name = item.GetName(); - try { infoLong = CustomHnS.AllHnSRoles.Contains(value) ? str : str[(str.IndexOf('\n') + 1)..str.Split("\n\n")[0].Length]; } - catch { infoLong = str; } - - GameObject.Find("PlayerOptionsMenu(Clone)").transform.FindChild("What Is This?").gameObject.SetActive(true); - GameSettingMenuPatch.GMButtons.ForEach(x => x.gameObject.SetActive(false)); - - var info = $"{value.ToColoredString()}: {infoLong}"; - GameSettingMenu.Instance.MenuDescriptionText.text = info; - - long now = Utils.TimeStamp; - bool startCoRoutine = now > HelpShowEndTS; - HelpShowEndTS = now + 15; - if (startCoRoutine) Main.Instance.StartCoroutine(CoRoutine()); - - IEnumerator CoRoutine() + if (Enum.GetValues().FindFirst(x => Translator.GetString($"{x}") == name.RemoveHtmlTags(), out CustomRoles value)) { - while (HelpShowEndTS > Utils.TimeStamp) - yield return new WaitForSecondsRealtime(1f); + string roleName = value.IsVanilla() ? value + "EHR" : value.ToString(); + string str = Translator.GetString($"{roleName}InfoLong").FixRoleName(value); + string infoLong; - GameObject gameObject = GameObject.Find("PlayerOptionsMenu(Clone)"); + try { infoLong = CustomHnS.AllHnSRoles.Contains(value) ? str : str[(str.IndexOf('\n') + 1)..str.Split("\n\n")[0].Length]; } + catch { infoLong = str; } - if (gameObject != null) + GameObject.Find("PlayerOptionsMenu(Clone)").transform.FindChild("What Is This?").gameObject.SetActive(true); + GameSettingMenuPatch.GMButtons.ForEach(x => x.gameObject.SetActive(false)); + + var info = $"{value.ToColoredString()}: {infoLong}"; + GameSettingMenu.Instance.MenuDescriptionText.text = info; + + long now = Utils.TimeStamp; + bool startCoRoutine = now > HelpShowEndTS; + HelpShowEndTS = now + 15; + if (startCoRoutine) Main.Instance.StartCoroutine(CoRoutine()); + + IEnumerator CoRoutine() { - Transform findChild = gameObject.transform.FindChild("What Is This?"); - if (findChild != null) findChild.gameObject.SetActive(false); - } + while (HelpShowEndTS > Utils.TimeStamp) + yield return new WaitForSecondsRealtime(1f); - GameSettingMenuPatch.GMButtons.ForEach(x => x.gameObject.SetActive(true)); + GameObject gameObject = GameObject.Find("PlayerOptionsMenu(Clone)"); + + if (gameObject != null) + { + Transform findChild = gameObject.transform.FindChild("What Is This?"); + if (findChild != null) findChild.gameObject.SetActive(false); + } + + GameSettingMenuPatch.GMButtons.ForEach(x => x.gameObject.SetActive(true)); + } } } })); @@ -844,72 +836,74 @@ public static class StringOptionPatch [HarmonyPrefix] private static bool UpdateValuePrefix(StringOption __instance) { - var item = ModGameOptionsMenu.GetFromBehaviour(__instance); - if (item == null) + if (ModGameOptionsMenu.OptionList.TryGetValue(__instance, out int index)) { - return true; - } - - item.SetValue(__instance.GetInt()); - string name = item.GetName(); + OptionItem item = OptionItem.AllOptions[index]; + item.SetValue(__instance.GetInt()); + string name = item.GetName(); - string name1 = name; + string name1 = name; - if (Main.CustomRoleValues.FindFirst(x => Translator.GetString($"{x}") == name1.RemoveHtmlTags(), out CustomRoles role)) - { - if (role.ToString().Contains("GuardianAngel")) role = CustomRoles.GA; - - name = name.RemoveHtmlTags(); - - switch (Options.UsePets.GetBool()) + if (Enum.GetValues().FindFirst(x => Translator.GetString($"{x}") == name1.RemoveHtmlTags(), out CustomRoles role)) { - case true when role.PetActivatedAbility(): - name += Translator.GetString("SupportsPetIndicator"); - break; - case false when role.OnlySpawnsWithPets(): - name += Translator.GetString("RequiresPetIndicator"); - Prompt.Show(Translator.GetString("Promt.RequiresPets"), () => Options.UsePets.SetValue(1), () => { }); - break; + if (role.ToString().Contains("GuardianAngel")) role = CustomRoles.GA; + + name = name.RemoveHtmlTags(); + + switch (Options.UsePets.GetBool()) + { + case true when role.PetActivatedAbility(): + name += Translator.GetString("SupportsPetIndicator"); + break; + case false when role.OnlySpawnsWithPets(): + name += Translator.GetString("RequiresPetIndicator"); + Prompt.Show(Translator.GetString("Promt.RequiresPets"), () => Options.UsePets.SetValue(1), () => { }); + break; + } + + if (role.IsExperimental()) name += $"{Translator.GetString("ExperimentalRoleIndicator")}"; + if (role.IsGhostRole()) name += GetGhostRoleTeam(role); + if (role.IsDevFavoriteRole()) name += " <#00ffff>★"; + + __instance.TitleText.fontWeight = FontWeight.Black; + __instance.TitleText.outlineColor = new(255, 255, 255, 255); + __instance.TitleText.outlineWidth = 0.04f; + __instance.LabelBackground.color = Utils.GetRoleColor(role); + __instance.TitleText.color = Color.white; + name = $"{name}"; + NotificationPopperPatch.AddRoleSettingsChangeMessage(item, role, true); } + else + NotificationPopperPatch.AddSettingsChangeMessage(item, true); - if (role.IsExperimental()) name += $"{Translator.GetString("ExperimentalRoleIndicator")}"; - if (role.IsGhostRole()) name += GetGhostRoleTeam(role); - if (role.IsDevFavoriteRole()) name += " <#00ffff>★"; - - __instance.TitleText.fontWeight = FontWeight.Black; - __instance.TitleText.outlineColor = new(255, 255, 255, 255); - __instance.TitleText.outlineWidth = 0.04f; - __instance.LabelBackground.color = Utils.GetRoleColor(role); - __instance.TitleText.color = Color.white; - name = $"{name}"; - NotificationPopperPatch.AddRoleSettingsChangeMessage(item, role, true); + __instance.TitleText.text = name; + return false; } - else - NotificationPopperPatch.AddSettingsChangeMessage(item, true); - __instance.TitleText.text = name; - return false; + return true; } [HarmonyPatch(nameof(StringOption.FixedUpdate))] [HarmonyPrefix] private static bool FixedUpdatePrefix(StringOption __instance) { - var item = ModGameOptionsMenu.GetFromBehaviour(__instance); - if (item == null) return true; - - __instance.MinusBtn.SetInteractable(true); - __instance.PlusBtn.SetInteractable(true); - - if (__instance.oldValue != __instance.Value && item is StringOptionItem stringOptionItem) + if (ModGameOptionsMenu.OptionList.TryGetValue(__instance, out int index)) { - __instance.oldValue = __instance.Value; - string selection = stringOptionItem.Selections[stringOptionItem.Rule.GetValueByIndex(__instance.Value)]; - if (!stringOptionItem.noTranslation) selection = Translator.GetString(selection); - __instance.ValueText.text = selection; + __instance.MinusBtn.SetInteractable(true); + __instance.PlusBtn.SetInteractable(true); + + if (__instance.oldValue != __instance.Value && OptionItem.AllOptions[index] is StringOptionItem stringOptionItem) + { + __instance.oldValue = __instance.Value; + string selection = stringOptionItem.Selections[stringOptionItem.Rule.GetValueByIndex(__instance.Value)]; + if (!stringOptionItem.noTranslation) selection = Translator.GetString(selection); + __instance.ValueText.text = selection; + } + + return false; } - return false; + return true; } [HarmonyPatch(nameof(StringOption.Increase))] @@ -946,7 +940,7 @@ public static class StringOptionPatch [HarmonyPatch(typeof(GameSettingMenu))] public static class GameSettingMenuPatch { - public static List GMButtons = []; + public static System.Collections.Generic.List GMButtons = []; private static readonly Vector3 ButtonPositionLeft = new(-3.9f, -0.55f, 0f); private static readonly Vector3 ButtonPositionRight = new(-2.4f, -0.55f, 0f); @@ -956,15 +950,15 @@ public static class GameSettingMenuPatch private static GameOptionsMenu TemplateGameOptionsMenu; private static PassiveButton TemplateGameSettingsButton; - private static Dictionary ModSettingsButtons = []; - private static Dictionary ModSettingsTabs = []; + private static System.Collections.Generic.Dictionary ModSettingsButtons = []; + private static System.Collections.Generic.Dictionary ModSettingsTabs = []; public static NumberOption PresetBehaviour; public static long LastPresetChange; public static FreeChatInputField InputField; - private static List HiddenBySearch = []; + private static System.Collections.Generic.List HiddenBySearch = []; public static Action SearchForOptionsAction; private static int NumImpsOnOpen = 1; @@ -1277,9 +1271,9 @@ public static class GameSettingMenuPatch string text = textField.textArea.text.Trim().ToLower(); var modTab = (TabGroup)(ModGameOptionsMenu.TabIndex - 3); OptionItem[] optionItems = Options.GroupedOptions[modTab]; - List result = optionItems.Where(x => x.Parent == null && !x.IsCurrentlyHidden() && !Translator.GetString($"{x.Name}").Contains(text, StringComparison.OrdinalIgnoreCase)).ToList(); + System.Collections.Generic.List result = optionItems.Where(x => x.Parent == null && !x.IsCurrentlyHidden() && !Translator.GetString($"{x.Name}").Contains(text, StringComparison.OrdinalIgnoreCase)).ToList(); HiddenBySearch = result; - List searchWinners = optionItems.Where(x => x.Parent == null && !x.IsCurrentlyHidden() && !result.Contains(x)).ToList(); + System.Collections.Generic.List searchWinners = optionItems.Where(x => x.Parent == null && !x.IsCurrentlyHidden() && !result.Contains(x)).ToList(); if (searchWinners.Count == 0 || !ModSettingsTabs.TryGetValue(modTab, out GameOptionsMenu gameSettings) || gameSettings == null) { @@ -1413,7 +1407,9 @@ public static class GameSettingMenuPatch SetDefaultButton(__instance); - ModGameOptionsMenu.ClearDictionaries(); + ModGameOptionsMenu.OptionList = new(); + ModGameOptionsMenu.BehaviourList = new(); + ModGameOptionsMenu.CategoryHeaderList = new(); ControllerManager.Instance.OpenOverlayMenu(__instance.name, __instance.BackButton, __instance.DefaultButtonSelected, __instance.ControllerSelectable); if (HudManager.InstanceExists) HudManager.Instance.menuNavigationPrompts.SetActive(false); @@ -1465,7 +1461,9 @@ public static class GameSettingMenuPatch foreach (GameOptionsMenu tab in ModSettingsTabs.Values) Object.Destroy(tab); foreach (GameObject button in GMButtons) Object.Destroy(button); - ModGameOptionsMenu.ClearDictionaries(); + ModSettingsButtons = []; + ModSettingsTabs = []; + GMButtons = []; Main.Instance.StartCoroutine(OptionShower.GetText()); } @@ -1514,4 +1512,4 @@ public static class RpcSyncSettingsPatch OptionItem.SyncAllOptions(); } -} +} \ No newline at end of file diff --git a/Patches/HudPatch.cs b/Patches/HudPatch.cs index 691ccaf56..90638f7b3 100644 --- a/Patches/HudPatch.cs +++ b/Patches/HudPatch.cs @@ -27,11 +27,11 @@ internal static class HudManagerPatch public static Color? CooldownTimerFlashColor = null; public static string AchievementUnlockedText = string.Empty; - public static TaskPanelBehaviour RoleTab; + private static TaskPanelBehaviour RoleTab; public static void ClearLowerInfoText() { - if (LowerInfoText == null) return; + if (!LowerInfoText) return; LowerInfoText.text = string.Empty; } @@ -44,11 +44,9 @@ internal static class HudManagerPatch PlayerControl player = PlayerControl.LocalPlayer; if (!player) return; - if (!__instance) return; - if (GameStates.IsLobby) { - if (PingTrackerUpdatePatch.Instance != null && SettingsText == null) + if (PingTrackerUpdatePatch.Instance && !SettingsText) { SettingsText = Object.Instantiate(__instance.KillButton.cooldownTimerText, __instance.transform, true); SettingsText.name = "EHR_SettingsText"; @@ -59,19 +57,19 @@ internal static class HudManagerPatch SettingsText.overflowMode = TextOverflowModes.Overflow; SettingsText.enableWordWrapping = false; } - else if (PingTrackerUpdatePatch.Instance == null && SettingsText != null) + else if (!PingTrackerUpdatePatch.Instance && SettingsText) { Object.Destroy(SettingsText.gameObject); SettingsText = null; } - if (SettingsText != null) + if (SettingsText) { SettingsText.text = OptionShower.GetTextNoFresh(); SettingsText.enabled = SettingsText.text != string.Empty; } } - else if (SettingsText != null) + else if (SettingsText) { Object.Destroy(SettingsText.gameObject); SettingsText = null; @@ -79,7 +77,7 @@ internal static class HudManagerPatch if (AmongUsClient.Instance.AmHost) { - if (OverriddenRolesText == null) + if (!OverriddenRolesText) { OverriddenRolesText = Object.Instantiate(__instance.KillButton.cooldownTimerText, __instance.transform, true); OverriddenRolesText.alignment = TextAlignmentOptions.Right; @@ -100,7 +98,7 @@ internal static class HudManagerPatch { PlayerControl pc = Utils.GetPlayerById(item.Key); string prefix = first ? string.Empty : "\n"; - var text = $"{prefix}{(item.Key == 0 ? "Host" : $"{(pc == null ? $"ID {item.Key}" : $"{pc.GetRealName()}")}")} - {GetString(item.Value.ToString())}"; + var text = $"{prefix}{(item.Key == 0 ? "Host" : $"{(!pc ? $"ID {item.Key}" : $"{pc.GetRealName()}")}")} - {GetString(item.Value.ToString())}"; resultText[item.Key] = text; first = false; } @@ -121,7 +119,7 @@ internal static class HudManagerPatch else { string prefix = first ? string.Empty : "\n"; - var text = $"{prefix}{(item.Key == 0 ? "Host" : $"{(pc == null ? $"ID {item.Key}" : $"{pc.GetRealName()}")}")} - <#ffffff>({GetString(role.ToString())}<#ffffff>)"; + var text = $"{prefix}{(item.Key == 0 ? "Host" : $"{(!pc ? $"ID {item.Key}" : $"{pc.GetRealName()}")}")} - <#ffffff>({GetString(role.ToString())}<#ffffff>)"; resultText[item.Key] = text; first = false; } @@ -138,7 +136,7 @@ internal static class HudManagerPatch if (Options.AutoGMRotationEnabled) { - if (AutoGMRotationStatusText == null) + if (!AutoGMRotationStatusText) { AutoGMRotationStatusText = Object.Instantiate(__instance.KillButton.cooldownTimerText, __instance.transform, true); AutoGMRotationStatusText.alignment = TextAlignmentOptions.Left; @@ -153,7 +151,7 @@ internal static class HudManagerPatch AutoGMRotationStatusText.text = BuildAutoGMRotationStatusText(false); AutoGMRotationStatusText.enabled = AutoGMRotationStatusText.text != string.Empty && GameStates.IsLobby; } - else if (AutoGMRotationStatusText != null) + else if (AutoGMRotationStatusText) { AutoGMRotationStatusText.text = string.Empty; AutoGMRotationStatusText.enabled = false; @@ -196,7 +194,7 @@ internal static class HudManagerPatch CustomRoles role = player.GetCustomRole(); - if (RoleTab == null) RoleTab = TaskPanelBehaviourPatch.CreateRoleTab(role); + if (!RoleTab) RoleTab = TaskPanelBehaviourPatch.CreateRoleTab(role); TaskPanelBehaviourPatch.UpdateRoleTab(RoleTab, role); bool usesPetInsteadOfKill = player.UsesPetInsteadOfKill(); @@ -247,7 +245,7 @@ internal static class HudManagerPatch case CustomRoles.CTFPlayer: __instance.AbilityButton?.OverrideText(GetString("CTF_ButtonText")); break; - case CustomRoles.RRPlayer when __instance.AbilityButton != null && RoomRush.VentLimit.TryGetValue(PlayerControl.LocalPlayer.PlayerId, out int ventLimit): + case CustomRoles.RRPlayer when __instance.AbilityButton && RoomRush.VentLimit.TryGetValue(PlayerControl.LocalPlayer.PlayerId, out int ventLimit): __instance.AbilityButton?.SetUsesRemaining(ventLimit); break; case CustomRoles.SnowdownPlayer: @@ -258,7 +256,7 @@ internal static class HudManagerPatch if (role.PetActivatedAbility() && Options.CurrentGameMode == CustomGameMode.Standard && player.GetRoleTypes() != RoleTypes.Engineer && !role.OnlySpawnsWithPets() && !role.AlwaysUsesPhantomBase() && !player.GetCustomSubRoles().Any(StartGameHostPatch.BasisChangingAddons.ContainsKey) && role is not CustomRoles.Changeling and not CustomRoles.Ninja and not CustomRoles.Duality and not CustomRoles.Witch and not CustomRoles.Silencer && (!role.SimpleAbilityTrigger() || !Options.UsePhantomBasis.GetBool() || !(player.IsNeutralKiller() && Options.UsePhantomBasisForNKs.GetBool())) && !(Options.UseMeetingShapeshift.GetBool() && player.UsesMeetingShapeshift()) && !role.ToString().EndsWith("EHR") && !role.IsVanilla()) __instance.AbilityButton?.Hide(); - if (LowerInfoText == null) + if (!LowerInfoText) { LowerInfoText = Object.Instantiate(__instance.KillButton.cooldownTimerText, __instance.transform, true); LowerInfoText.alignment = TextAlignmentOptions.Center; @@ -571,7 +569,7 @@ internal static class SetHudActivePatch { if (GameStates.IsLobby || !isActive) __instance?.ReportButton?.ToggleVisible(false); - if (__instance == null) + if (!__instance) { Logger.Fatal("HudManager __instance ended up being null", "SetHudActivePatch.Postfix"); return; @@ -642,7 +640,7 @@ internal static class SetHudActivePatch } PlayerControl player = PlayerControl.LocalPlayer; - if (player == null) return; + if (!player) return; switch (player.GetCustomRole()) { @@ -726,7 +724,7 @@ internal static class HudManagerStartPatch { foreach (AspectPosition aspect in HudManager.Instance.transform.FindChild("Buttons").GetComponentsInChildren(true)) { - if (aspect.gameObject == null) continue; + if (!aspect.gameObject) continue; if (aspect.gameObject.transform.parent.name == "TopRight") continue; if (aspect.gameObject.transform.parent.transform.parent.name == "TopRight") continue; @@ -737,7 +735,7 @@ internal static class HudManagerStartPatch foreach (ActionButton button in HudManager.Instance.GetComponentsInChildren(true)) { - if (button.gameObject == null) continue; + if (!button.gameObject) continue; button.gameObject.SetActive(!button.isActiveAndEnabled); button.gameObject.transform.localScale *= scaleFactor; @@ -818,7 +816,7 @@ internal static class SabotageMapPatch foreach (MapRoom mr in __instance.rooms) { - if (mr.special == null || mr.special.transform == null) continue; + if (!mr.special || !mr.special.transform) continue; SystemTypes room = mr.room; @@ -893,7 +891,7 @@ internal static class MapRoomDoorsUpdatePatch { var autoOpenDoor = door.TryCast(); - if (autoOpenDoor != null) + if (autoOpenDoor) { total = 30f; timer = autoOpenDoor.CooldownTimer; @@ -1347,7 +1345,7 @@ internal static class TaskPanelBehaviourPatch PlayerControl player = PlayerControl.LocalPlayer; - if (taskList == "None" || GameStates.IsLobby || player == null) return; + if (taskList == "None" || GameStates.IsLobby || !player) return; NetworkedPlayerInfo data = PlayerControl.LocalPlayer.Data; if (data && data.Role) taskList = taskList.Replace($"\n{data.Role.NiceName} {TranslationController.Instance.GetString(StringNames.RoleHint)}\n{data.Role.BlurbMed}", string.Empty); diff --git a/Patches/OutroPatch.cs b/Patches/OutroPatch.cs index 63e88529b..ea1c9617b 100644 --- a/Patches/OutroPatch.cs +++ b/Patches/OutroPatch.cs @@ -456,11 +456,12 @@ internal static class SetEverythingUpPatch IEnumerator SetupPoolablePlayers() { - if (Camera.main == null) yield break; + Camera main = Camera.main; + if (!main) yield break; yield return null; - Vector3 pos = Camera.main.ViewportToWorldPoint(new(0f, 1f, Camera.main.nearClipPlane)); + Vector3 pos = main.ViewportToWorldPoint(new(0f, 1f, main.nearClipPlane)); GameObject roleSummaryObject = Object.Instantiate(__instance.WinText.gameObject); roleSummaryObject.transform.position = new(__instance.Navigation.ExitButton.transform.position.x + 0.1f, pos.y - 0.1f, -15f); roleSummaryObject.transform.localScale = new(1f, 1f, 1f); diff --git a/Patches/ShipStatusPatch.cs b/Patches/ShipStatusPatch.cs index 7a1758e5f..87a2378f7 100644 --- a/Patches/ShipStatusPatch.cs +++ b/Patches/ShipStatusPatch.cs @@ -551,7 +551,7 @@ internal static class VentilationSystemDeterioratePatch { int vents = ShipStatus.Instance.AllVents.Count(vent => !pc.CanUseVent(vent.Id)); if (allPlayers.Count >= vents) continue; - MessageWriter writer = MessageWriter.Get(SendOption.Reliable); + MessageWriter writer = MessageWriter.Get(); writer.StartMessage(6); writer.Write(AmongUsClient.Instance.GameId); writer.WritePacked(pc.OwnerId); diff --git a/Roles/Standard/Addons/Common/Asthmatic.cs b/Roles/Standard/Addons/Common/Asthmatic.cs index bc4978077..bd583148d 100644 --- a/Roles/Standard/Addons/Common/Asthmatic.cs +++ b/Roles/Standard/Addons/Common/Asthmatic.cs @@ -74,7 +74,7 @@ internal class Asthmatic : IAddon foreach (PlayerControl pc in Main.EnumerateAlivePlayerControls()) { if (pc.Is(CustomRoles.Asthmatic)) - Timers[pc.PlayerId] = new(30, r.Next(MinRedTime, MaxRedTime), now, '●', false, RandomRedTime, RandomGreenTime); + Timers[pc.PlayerId] = new(30, r.Next(MinRedTime, MaxRedTime), '●', false, RandomRedTime, RandomGreenTime); } }, 8f, log: false); } diff --git a/Roles/Standard/Crewmate/Chaos/Tornado.cs b/Roles/Standard/Crewmate/Chaos/Tornado.cs index a90d184c2..50049fcba 100644 --- a/Roles/Standard/Crewmate/Chaos/Tornado.cs +++ b/Roles/Standard/Crewmate/Chaos/Tornado.cs @@ -116,8 +116,6 @@ internal class Tornado : RoleBase public static void SpawnTornado(PlayerControl pc) { - if (pc == null) return; - (Vector2 Location, string RoomName) info = pc.GetPositionInfo(); long now = TimeStamp; Tornados.TryAdd(info, now); @@ -127,27 +125,27 @@ internal class Tornado : RoleBase public override void OnCheckPlayerPosition(PlayerControl pc) { - if (!IsEnable || !GameStates.IsInTask || Tornados.Count == 0 || pc == null) return; + if (!IsEnable || !GameStates.IsInTask || Tornados.Count == 0) return; long now = TimeStamp; if (!pc.Is(CustomRoles.Tornado)) { - var Random = IRandom.Instance; - string NotifyString = GetString("TeleportedByTornado"); + var random = IRandom.Instance; + string notifyString = GetString("TeleportedByTornado"); float tornadoRange = TornadoRange.GetFloat(); int tornadoDuration = TornadoDuration.GetInt(); - foreach (KeyValuePair<(Vector2 Location, string RoomName), long> tornado in Tornados) + foreach (KeyValuePair<(Vector2 Location, string RoomName), long> tornado in Tornados.ToArray()) { if (FastVector2.DistanceWithinRange(tornado.Key.Location, pc.Pos(), tornadoRange)) { - if (!CanUseMap || Random.Next(0, 100) < 50) + if (!CanUseMap || random.Next(0, 100) < 50) pc.TPToRandomVent(); else Map.RandomTeleport(pc); - pc.Notify(NotifyString); + pc.Notify(notifyString); } if (tornado.Value + tornadoDuration < now) diff --git a/Roles/Standard/Crewmate/Support/Altruist.cs b/Roles/Standard/Crewmate/Support/Altruist.cs index 1f5bb7cce..781639652 100644 --- a/Roles/Standard/Crewmate/Support/Altruist.cs +++ b/Roles/Standard/Crewmate/Support/Altruist.cs @@ -120,7 +120,7 @@ public class Altruist : RoleBase { try { - if (!ReviveTargetsKillerGetsArrow.GetBool()) return; + if (!On || !ReviveTargetsKillerGetsArrow.GetBool()) return; foreach (PlayerControl pc in Main.EnumeratePlayerControls()) { diff --git a/Roles/Standard/Neutral/Killing/Necromancer.cs b/Roles/Standard/Neutral/Killing/Necromancer.cs index f858ea0da..6037d4c8a 100644 --- a/Roles/Standard/Neutral/Killing/Necromancer.cs +++ b/Roles/Standard/Neutral/Killing/Necromancer.cs @@ -138,7 +138,7 @@ internal class Necromancer : RoleBase { if (!GameStates.IsInTask || ExileController.Instance) return; - if (!NecromancerPC.IsAlive() && Deathknight.DeathknightPC.IsAlive()) + if ((NecromancerPC == null || !NecromancerPC.IsAlive()) && (Deathknight.DeathknightPC != null && Deathknight.DeathknightPC.IsAlive())) { Deathknight.DeathknightPC.RpcSetCustomRole(CustomRoles.Necromancer); Deathknight.DeathknightPC = null;