summaryrefslogtreecommitdiff
path: root/Client/Assembly-CSharp
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2020-12-30 20:59:04 +0800
committerchai <chaifix@163.com>2020-12-30 20:59:04 +0800
commite9ea621b93fbb58d9edfca8375918791637bbd52 (patch)
tree19ce3b1c1f2d51eda6878c9d0f2c9edc27f13650 /Client/Assembly-CSharp
+init
Diffstat (limited to 'Client/Assembly-CSharp')
-rw-r--r--Client/Assembly-CSharp/AcceptDivertPowerGame.cs84
-rw-r--r--Client/Assembly-CSharp/AdDataCollectScreen.cs65
-rw-r--r--Client/Assembly-CSharp/AdPlayer.cs118
-rw-r--r--Client/Assembly-CSharp/AlignGame.cs146
-rw-r--r--Client/Assembly-CSharp/AlphaBlink.cs44
-rw-r--r--Client/Assembly-CSharp/AlphaPulse.cs43
-rw-r--r--Client/Assembly-CSharp/AmongUsClient.cs497
-rw-r--r--Client/Assembly-CSharp/AmongUsProduct.cs9
-rw-r--r--Client/Assembly-CSharp/Announcement.cs10
-rw-r--r--Client/Assembly-CSharp/AnnouncementPopUp.cs154
-rw-r--r--Client/Assembly-CSharp/ArrowBehaviour.cs47
-rw-r--r--Client/Assembly-CSharp/AspectPosition.cs86
-rw-r--r--Client/Assembly-CSharp/AspectSize.cs32
-rw-r--r--Client/Assembly-CSharp/Assembly-CSharp.csproj464
-rw-r--r--Client/Assembly-CSharp/Assets/CoreScripts/Telemetry.cs300
-rw-r--r--Client/Assembly-CSharp/Asteroid.cs71
-rw-r--r--Client/Assembly-CSharp/AutoOpenDoor.cs37
-rw-r--r--Client/Assembly-CSharp/BanButton.cs52
-rw-r--r--Client/Assembly-CSharp/BanMenu.cs153
-rw-r--r--Client/Assembly-CSharp/BlockedWords.cs877
-rw-r--r--Client/Assembly-CSharp/BoolRange.cs10
-rw-r--r--Client/Assembly-CSharp/ButtonBehavior.cs64
-rw-r--r--Client/Assembly-CSharp/ButtonRolloverHandler.cs35
-rw-r--r--Client/Assembly-CSharp/CardSlideGame.cs190
-rw-r--r--Client/Assembly-CSharp/ChainBehaviour.cs27
-rw-r--r--Client/Assembly-CSharp/ChatBubble.cs83
-rw-r--r--Client/Assembly-CSharp/ChatController.cs326
-rw-r--r--Client/Assembly-CSharp/ChatNoteTypes.cs6
-rw-r--r--Client/Assembly-CSharp/CloudGenerator.cs159
-rw-r--r--Client/Assembly-CSharp/ColorChip.cs11
-rw-r--r--Client/Assembly-CSharp/ConditionalHide.cs21
-rw-r--r--Client/Assembly-CSharp/ConditionalStore.cs9
-rw-r--r--Client/Assembly-CSharp/Console.cs97
-rw-r--r--Client/Assembly-CSharp/Constants.cs90
-rw-r--r--Client/Assembly-CSharp/Controller.cs157
-rw-r--r--Client/Assembly-CSharp/CooldownHelpers.cs33
-rw-r--r--Client/Assembly-CSharp/CounterArea.cs44
-rw-r--r--Client/Assembly-CSharp/CourseMinigame.cs206
-rw-r--r--Client/Assembly-CSharp/CourseStarBehaviour.cs17
-rw-r--r--Client/Assembly-CSharp/CreateGameOptions.cs104
-rw-r--r--Client/Assembly-CSharp/CreateOptionsPicker.cs165
-rw-r--r--Client/Assembly-CSharp/CreateStoreButton.cs16
-rw-r--r--Client/Assembly-CSharp/CrewVisualizer.cs63
-rw-r--r--Client/Assembly-CSharp/CrossFadeImages.cs20
-rw-r--r--Client/Assembly-CSharp/CrossFader.cs74
-rw-r--r--Client/Assembly-CSharp/CrystalBehaviour.cs110
-rw-r--r--Client/Assembly-CSharp/CrystalMinigame.cs120
-rw-r--r--Client/Assembly-CSharp/CustomNetworkTransform.cs265
-rw-r--r--Client/Assembly-CSharp/CustomPlayerMenu.cs41
-rw-r--r--Client/Assembly-CSharp/DataCollectScreen.cs56
-rw-r--r--Client/Assembly-CSharp/DeadBody.cs35
-rw-r--r--Client/Assembly-CSharp/DeathReason.cs8
-rw-r--r--Client/Assembly-CSharp/DeconSystem.cs163
-rw-r--r--Client/Assembly-CSharp/DefaultPool.cs82
-rw-r--r--Client/Assembly-CSharp/DemoKeyboardStick.cs25
-rw-r--r--Client/Assembly-CSharp/DestroyableSingleton.cs58
-rw-r--r--Client/Assembly-CSharp/DialBehaviour.cs46
-rw-r--r--Client/Assembly-CSharp/DialogueBox.cs27
-rw-r--r--Client/Assembly-CSharp/DisconnectPopup.cs112
-rw-r--r--Client/Assembly-CSharp/DiscordManager.cs207
-rw-r--r--Client/Assembly-CSharp/DiscoveryState.cs7
-rw-r--r--Client/Assembly-CSharp/DiscussBehaviour.cs65
-rw-r--r--Client/Assembly-CSharp/DivertPowerMetagame.cs25
-rw-r--r--Client/Assembly-CSharp/DivertPowerMinigame.cs91
-rw-r--r--Client/Assembly-CSharp/DivertPowerTask.cs51
-rw-r--r--Client/Assembly-CSharp/DoorsSystemType.cs119
-rw-r--r--Client/Assembly-CSharp/DotAligner.cs43
-rw-r--r--Client/Assembly-CSharp/DragState.cs9
-rw-r--r--Client/Assembly-CSharp/DummyBehaviour.cs63
-rw-r--r--Client/Assembly-CSharp/DummyConsole.cs57
-rw-r--r--Client/Assembly-CSharp/DynamicSound.cs26
-rw-r--r--Client/Assembly-CSharp/Effects.cs248
-rw-r--r--Client/Assembly-CSharp/ElectricTask.cs82
-rw-r--r--Client/Assembly-CSharp/EmergencyMinigame.cs120
-rw-r--r--Client/Assembly-CSharp/EmptyGarbageMinigame.cs195
-rw-r--r--Client/Assembly-CSharp/EndGameManager.cs236
-rw-r--r--Client/Assembly-CSharp/EngineBehaviour.cs48
-rw-r--r--Client/Assembly-CSharp/EnterCodeMinigame.cs121
-rw-r--r--Client/Assembly-CSharp/ExileController.cs160
-rw-r--r--Client/Assembly-CSharp/ExitGameButton.cs24
-rw-r--r--Client/Assembly-CSharp/Extensions.cs409
-rw-r--r--Client/Assembly-CSharp/FindAGameManager.cs124
-rw-r--r--Client/Assembly-CSharp/FindGameButton.cs63
-rw-r--r--Client/Assembly-CSharp/FingerBehaviour.cs101
-rw-r--r--Client/Assembly-CSharp/FixedActionConsole.cs64
-rw-r--r--Client/Assembly-CSharp/FlatWaveBehaviour.cs75
-rw-r--r--Client/Assembly-CSharp/FloatRange.cs159
-rw-r--r--Client/Assembly-CSharp/FollowerCamera.cs54
-rw-r--r--Client/Assembly-CSharp/FontCache.cs78
-rw-r--r--Client/Assembly-CSharp/FontData.cs32
-rw-r--r--Client/Assembly-CSharp/FontExtensionData.cs56
-rw-r--r--Client/Assembly-CSharp/FontLoader.cs106
-rw-r--r--Client/Assembly-CSharp/GameData.cs556
-rw-r--r--Client/Assembly-CSharp/GameDiscovery.cs83
-rw-r--r--Client/Assembly-CSharp/GameModes.cs8
-rw-r--r--Client/Assembly-CSharp/GameObjectExtensions.cs77
-rw-r--r--Client/Assembly-CSharp/GameOptionsData.cs332
-rw-r--r--Client/Assembly-CSharp/GameOptionsMenu.cs133
-rw-r--r--Client/Assembly-CSharp/GameOverReason.cs12
-rw-r--r--Client/Assembly-CSharp/GameSettingMenu.cs37
-rw-r--r--Client/Assembly-CSharp/GameStartManager.cs215
-rw-r--r--Client/Assembly-CSharp/GarbageBehaviour.cs13
-rw-r--r--Client/Assembly-CSharp/GoogleMobileAds/Api/AdErrorEventArgs.cs9
-rw-r--r--Client/Assembly-CSharp/GoogleMobileAds/Api/AdFailedToLoadEventArgs.cs9
-rw-r--r--Client/Assembly-CSharp/GoogleMobileAds/Api/AdLoader.cs93
-rw-r--r--Client/Assembly-CSharp/GoogleMobileAds/Api/AdPosition.cs15
-rw-r--r--Client/Assembly-CSharp/GoogleMobileAds/Api/AdRequest.cs113
-rw-r--r--Client/Assembly-CSharp/GoogleMobileAds/Api/AdSize.cs88
-rw-r--r--Client/Assembly-CSharp/GoogleMobileAds/Api/AdapterState.cs10
-rw-r--r--Client/Assembly-CSharp/GoogleMobileAds/Api/AdapterStatus.cs20
-rw-r--r--Client/Assembly-CSharp/GoogleMobileAds/Api/BannerView.cs121
-rw-r--r--Client/Assembly-CSharp/GoogleMobileAds/Api/CustomNativeEventArgs.cs9
-rw-r--r--Client/Assembly-CSharp/GoogleMobileAds/Api/CustomNativeTemplateAd.cs52
-rw-r--r--Client/Assembly-CSharp/GoogleMobileAds/Api/Gender.cs11
-rw-r--r--Client/Assembly-CSharp/GoogleMobileAds/Api/InterstitialAd.cs88
-rw-r--r--Client/Assembly-CSharp/GoogleMobileAds/Api/Mediation/MediationExtras.cs19
-rw-r--r--Client/Assembly-CSharp/GoogleMobileAds/Api/MobileAds.cs37
-rw-r--r--Client/Assembly-CSharp/GoogleMobileAds/Api/NativeAdType.cs9
-rw-r--r--Client/Assembly-CSharp/GoogleMobileAds/Api/Reward.cs11
-rw-r--r--Client/Assembly-CSharp/GoogleMobileAds/Api/RewardBasedVideoAd.cs125
-rw-r--r--Client/Assembly-CSharp/GoogleMobileAds/Api/RewardedAd.cs97
-rw-r--r--Client/Assembly-CSharp/GoogleMobileAds/Api/ServerSideVerificationOptions.cs41
-rw-r--r--Client/Assembly-CSharp/GoogleMobileAds/Common/DummyClient.cs185
-rw-r--r--Client/Assembly-CSharp/GoogleMobileAds/Common/IAdLoaderClient.cs14
-rw-r--r--Client/Assembly-CSharp/GoogleMobileAds/Common/IBannerClient.cs40
-rw-r--r--Client/Assembly-CSharp/GoogleMobileAds/Common/ICustomNativeTemplateClient.cs20
-rw-r--r--Client/Assembly-CSharp/GoogleMobileAds/Common/IInterstitialClient.cs30
-rw-r--r--Client/Assembly-CSharp/GoogleMobileAds/Common/IMobileAdsClient.cs15
-rw-r--r--Client/Assembly-CSharp/GoogleMobileAds/Common/IRewardBasedVideoAdClient.cs36
-rw-r--r--Client/Assembly-CSharp/GoogleMobileAds/Common/IRewardedAdClient.cs32
-rw-r--r--Client/Assembly-CSharp/GoogleMobileAds/Common/MobileAdsEventExecutor.cs72
-rw-r--r--Client/Assembly-CSharp/GoogleMobileAds/Common/RewardedAdDummyClient.cs59
-rw-r--r--Client/Assembly-CSharp/GoogleMobileAds/Common/Utils.cs27
-rw-r--r--Client/Assembly-CSharp/GoogleMobileAds/GoogleMobileAdsClientFactory.cs39
-rw-r--r--Client/Assembly-CSharp/HashRandom.cs36
-rw-r--r--Client/Assembly-CSharp/HatBehaviour.cs34
-rw-r--r--Client/Assembly-CSharp/HatManager.cs89
-rw-r--r--Client/Assembly-CSharp/HatsTab.cs83
-rw-r--r--Client/Assembly-CSharp/HorizontalGauge.cs26
-rw-r--r--Client/Assembly-CSharp/HostGameButton.cs135
-rw-r--r--Client/Assembly-CSharp/HowToPlayController.cs67
-rw-r--r--Client/Assembly-CSharp/HudManager.cs312
-rw-r--r--Client/Assembly-CSharp/HudOverrideSystemType.cs40
-rw-r--r--Client/Assembly-CSharp/HudOverrideTask.cs82
-rw-r--r--Client/Assembly-CSharp/IActivatable.cs6
-rw-r--r--Client/Assembly-CSharp/IBuyable.cs6
-rw-r--r--Client/Assembly-CSharp/IBytesSerializable.cs6
-rw-r--r--Client/Assembly-CSharp/IConnectButton.cs8
-rw-r--r--Client/Assembly-CSharp/IDisconnectHandler.cs9
-rw-r--r--Client/Assembly-CSharp/IFocusHolder.cs11
-rw-r--r--Client/Assembly-CSharp/IGameListHandler.cs8
-rw-r--r--Client/Assembly-CSharp/ILocationActivate.cs6
-rw-r--r--Client/Assembly-CSharp/IObjectPool.cs13
-rw-r--r--Client/Assembly-CSharp/ISoundPlayer.cs11
-rw-r--r--Client/Assembly-CSharp/ISystemType.cs15
-rw-r--r--Client/Assembly-CSharp/ITranslatedText.cs6
-rw-r--r--Client/Assembly-CSharp/IUsable.cs14
-rw-r--r--Client/Assembly-CSharp/IVirtualJoystick.cs7
-rw-r--r--Client/Assembly-CSharp/ImageData.cs10
-rw-r--r--Client/Assembly-CSharp/ImageNames.cs12
-rw-r--r--Client/Assembly-CSharp/ImageTranslator.cs24
-rw-r--r--Client/Assembly-CSharp/ImportantTextTask.cs41
-rw-r--r--Client/Assembly-CSharp/InfectedOverlay.cs51
-rw-r--r--Client/Assembly-CSharp/InnerNet/AlterGameTags.cs9
-rw-r--r--Client/Assembly-CSharp/InnerNet/ClientData.cs21
-rw-r--r--Client/Assembly-CSharp/InnerNet/DisconnectReasons.cs25
-rw-r--r--Client/Assembly-CSharp/InnerNet/GameKeywords.cs16
-rw-r--r--Client/Assembly-CSharp/InnerNet/GameListing.cs30
-rw-r--r--Client/Assembly-CSharp/InnerNet/GameStates.cs12
-rw-r--r--Client/Assembly-CSharp/InnerNet/InnerDiscover.cs114
-rw-r--r--Client/Assembly-CSharp/InnerNet/InnerNetClient.cs1726
-rw-r--r--Client/Assembly-CSharp/InnerNet/InnerNetObject.cs74
-rw-r--r--Client/Assembly-CSharp/InnerNet/InnerNetServer.cs592
-rw-r--r--Client/Assembly-CSharp/InnerNet/JoinFailureReasons.cs15
-rw-r--r--Client/Assembly-CSharp/InnerNet/LimboStates.cs11
-rw-r--r--Client/Assembly-CSharp/InnerNet/MatchMakerModes.cs11
-rw-r--r--Client/Assembly-CSharp/InnerNet/MessageExtensions.cs24
-rw-r--r--Client/Assembly-CSharp/InnerNet/SpawnFlags.cs11
-rw-r--r--Client/Assembly-CSharp/InnerNet/Tags.cs35
-rw-r--r--Client/Assembly-CSharp/IntRange.cs71
-rw-r--r--Client/Assembly-CSharp/IntroCutscene.cs155
-rw-r--r--Client/Assembly-CSharp/JoinGameButton.cs119
-rw-r--r--Client/Assembly-CSharp/KerningPair.cs11
-rw-r--r--Client/Assembly-CSharp/KeyboardJoystick.cs79
-rw-r--r--Client/Assembly-CSharp/KeypadGame.cs135
-rw-r--r--Client/Assembly-CSharp/KillAnimType.cs10
-rw-r--r--Client/Assembly-CSharp/KillAnimation.cs52
-rw-r--r--Client/Assembly-CSharp/KillButtonManager.cs69
-rw-r--r--Client/Assembly-CSharp/KillOverlay.cs114
-rw-r--r--Client/Assembly-CSharp/LanguageButton.cs12
-rw-r--r--Client/Assembly-CSharp/LanguageSetter.cs50
-rw-r--r--Client/Assembly-CSharp/LanguageUnit.cs79
-rw-r--r--Client/Assembly-CSharp/LeafBehaviour.cs40
-rw-r--r--Client/Assembly-CSharp/LeafMinigame.cs104
-rw-r--r--Client/Assembly-CSharp/LetterTree.cs299
-rw-r--r--Client/Assembly-CSharp/LifeSuppSystemType.cs121
-rw-r--r--Client/Assembly-CSharp/LightSource.cs335
-rw-r--r--Client/Assembly-CSharp/LobbyBehaviour.cs82
-rw-r--r--Client/Assembly-CSharp/MMOnlineManager.cs28
-rw-r--r--Client/Assembly-CSharp/MainMenuManager.cs66
-rw-r--r--Client/Assembly-CSharp/ManualDoor.cs90
-rw-r--r--Client/Assembly-CSharp/MapBehaviour.cs113
-rw-r--r--Client/Assembly-CSharp/MapConsole.cs65
-rw-r--r--Client/Assembly-CSharp/MapCountOverlay.cs90
-rw-r--r--Client/Assembly-CSharp/MapRoom.cs92
-rw-r--r--Client/Assembly-CSharp/MapTaskOverlay.cs101
-rw-r--r--Client/Assembly-CSharp/MatchMaker.cs41
-rw-r--r--Client/Assembly-CSharp/MatchMakerGameButton.cs59
-rw-r--r--Client/Assembly-CSharp/MedScanMinigame.cs197
-rw-r--r--Client/Assembly-CSharp/MedScanSystem.cs81
-rw-r--r--Client/Assembly-CSharp/MeetingHud.cs734
-rw-r--r--Client/Assembly-CSharp/MeetingRoomManager.cs36
-rw-r--r--Client/Assembly-CSharp/MemSafeStringExtensions.cs37
-rw-r--r--Client/Assembly-CSharp/MeshRendererExtensions.cs23
-rw-r--r--Client/Assembly-CSharp/Minigame.cs166
-rw-r--r--Client/Assembly-CSharp/MonoPInvokeCallbackAttribute.cs8
-rw-r--r--Client/Assembly-CSharp/NameTextBehaviour.cs61
-rw-r--r--Client/Assembly-CSharp/NavigationMinigame.cs88
-rw-r--r--Client/Assembly-CSharp/NoOxyTask.cs106
-rw-r--r--Client/Assembly-CSharp/NoShadowBehaviour.cs55
-rw-r--r--Client/Assembly-CSharp/NormalPlayerTask.cs284
-rw-r--r--Client/Assembly-CSharp/NotificationPopper.cs58
-rw-r--r--Client/Assembly-CSharp/NumberOption.cs111
-rw-r--r--Client/Assembly-CSharp/ObjectPoolBehavior.cs138
-rw-r--r--Client/Assembly-CSharp/OffsetAdjustment.cs11
-rw-r--r--Client/Assembly-CSharp/OneWayShadows.cs22
-rw-r--r--Client/Assembly-CSharp/OptionBehaviour.cs33
-rw-r--r--Client/Assembly-CSharp/OptionsConsole.cs64
-rw-r--r--Client/Assembly-CSharp/OptionsMenuBehaviour.cs200
-rw-r--r--Client/Assembly-CSharp/OverlayKillAnimation.cs150
-rw-r--r--Client/Assembly-CSharp/Palette.cs67
-rw-r--r--Client/Assembly-CSharp/ParallaxController.cs22
-rw-r--r--Client/Assembly-CSharp/ParticleInfo.cs12
-rw-r--r--Client/Assembly-CSharp/PassiveButton.cs47
-rw-r--r--Client/Assembly-CSharp/PassiveButtonManager.cs256
-rw-r--r--Client/Assembly-CSharp/PetBehaviour.cs140
-rw-r--r--Client/Assembly-CSharp/PetsTab.cs78
-rw-r--r--Client/Assembly-CSharp/PhysicsHelpers.cs38
-rw-r--r--Client/Assembly-CSharp/PingTracker.cs19
-rw-r--r--Client/Assembly-CSharp/PlayerAnimator.cs90
-rw-r--r--Client/Assembly-CSharp/PlayerControl.cs1470
-rw-r--r--Client/Assembly-CSharp/PlayerParticle.cs39
-rw-r--r--Client/Assembly-CSharp/PlayerParticleInfo.cs12
-rw-r--r--Client/Assembly-CSharp/PlayerParticles.cs73
-rw-r--r--Client/Assembly-CSharp/PlayerPhysics.cs330
-rw-r--r--Client/Assembly-CSharp/PlayerTab.cs100
-rw-r--r--Client/Assembly-CSharp/PlayerTask.cs137
-rw-r--r--Client/Assembly-CSharp/PlayerVoteArea.cs211
-rw-r--r--Client/Assembly-CSharp/PoolableBehavior.cs17
-rw-r--r--Client/Assembly-CSharp/PoolablePlayer.cs45
-rw-r--r--Client/Assembly-CSharp/PooledMapIcon.cs35
-rw-r--r--Client/Assembly-CSharp/PowerTools/SpriteAnim.cs255
-rw-r--r--Client/Assembly-CSharp/PowerTools/SpriteAnimEventHandler.cs111
-rw-r--r--Client/Assembly-CSharp/PowerTools/SpriteAnimNodeSync.cs36
-rw-r--r--Client/Assembly-CSharp/PowerTools/SpriteAnimNodes.cs232
-rw-r--r--Client/Assembly-CSharp/PowerTools/WaitForAnimationFinish.cs55
-rw-r--r--Client/Assembly-CSharp/ProgressTracker.cs39
-rw-r--r--Client/Assembly-CSharp/Properties/AssemblyInfo.cs6
-rw-r--r--Client/Assembly-CSharp/PurchaseButton.cs90
-rw-r--r--Client/Assembly-CSharp/PurchaseStates.cs9
-rw-r--r--Client/Assembly-CSharp/RadioWaveBehaviour.cs81
-rw-r--r--Client/Assembly-CSharp/RandomFill.cs33
-rw-r--r--Client/Assembly-CSharp/ReactorMinigame.cs110
-rw-r--r--Client/Assembly-CSharp/ReactorRoomWire.cs51
-rw-r--r--Client/Assembly-CSharp/ReactorShipRoom.cs74
-rw-r--r--Client/Assembly-CSharp/ReactorSystemType.cs137
-rw-r--r--Client/Assembly-CSharp/ReactorTask.cs85
-rw-r--r--Client/Assembly-CSharp/RefuelMinigame.cs23
-rw-r--r--Client/Assembly-CSharp/RefuelStage.cs98
-rw-r--r--Client/Assembly-CSharp/ReportButtonManager.cs28
-rw-r--r--Client/Assembly-CSharp/ResSetter.cs29
-rw-r--r--Client/Assembly-CSharp/ResolutionManager.cs44
-rw-r--r--Client/Assembly-CSharp/ResolutionSlider.cs73
-rw-r--r--Client/Assembly-CSharp/RingBuffer.cs75
-rw-r--r--Client/Assembly-CSharp/RoomTracker.cs159
-rw-r--r--Client/Assembly-CSharp/SabotageSystemType.cs135
-rw-r--r--Client/Assembly-CSharp/SabotageTask.cs33
-rw-r--r--Client/Assembly-CSharp/SampleMinigame.cs382
-rw-r--r--Client/Assembly-CSharp/SaveManager.cs750
-rw-r--r--Client/Assembly-CSharp/Scene0Controller.cs79
-rw-r--r--Client/Assembly-CSharp/Scene1Controller.cs94
-rw-r--r--Client/Assembly-CSharp/SceneChanger.cs27
-rw-r--r--Client/Assembly-CSharp/SceneController.cs6
-rw-r--r--Client/Assembly-CSharp/ScreenJoystick.cs54
-rw-r--r--Client/Assembly-CSharp/Scroller.cs85
-rw-r--r--Client/Assembly-CSharp/SecurityCameraSystemType.cs78
-rw-r--r--Client/Assembly-CSharp/ServerInfo.cs43
-rw-r--r--Client/Assembly-CSharp/ServerManager.cs59
-rw-r--r--Client/Assembly-CSharp/ServerSelectUi.cs59
-rw-r--r--Client/Assembly-CSharp/ServerSelector.cs53
-rw-r--r--Client/Assembly-CSharp/SettingsMode.cs7
-rw-r--r--Client/Assembly-CSharp/ShadowCamera.cs17
-rw-r--r--Client/Assembly-CSharp/ShhhBehaviour.cs135
-rw-r--r--Client/Assembly-CSharp/ShieldMinigame.cs84
-rw-r--r--Client/Assembly-CSharp/ShipRoom.cs15
-rw-r--r--Client/Assembly-CSharp/ShipStatus.cs738
-rw-r--r--Client/Assembly-CSharp/ShowAdsState.cs9
-rw-r--r--Client/Assembly-CSharp/SimonSaysGame.cs243
-rw-r--r--Client/Assembly-CSharp/SinglePopHelp.cs6
-rw-r--r--Client/Assembly-CSharp/SkinData.cs48
-rw-r--r--Client/Assembly-CSharp/SkinLayer.cs101
-rw-r--r--Client/Assembly-CSharp/SkinsTab.cs83
-rw-r--r--Client/Assembly-CSharp/SlideBar.cs78
-rw-r--r--Client/Assembly-CSharp/SortGameObject.cs16
-rw-r--r--Client/Assembly-CSharp/SortMinigame.cs72
-rw-r--r--Client/Assembly-CSharp/SoundGroup.cs13
-rw-r--r--Client/Assembly-CSharp/SoundManager.cs239
-rw-r--r--Client/Assembly-CSharp/SoundStarter.cs23
-rw-r--r--Client/Assembly-CSharp/SpinAnimator.cs72
-rw-r--r--Client/Assembly-CSharp/SpriteParticle.cs128
-rw-r--r--Client/Assembly-CSharp/StarGen.cs170
-rw-r--r--Client/Assembly-CSharp/StatsManager.cs439
-rw-r--r--Client/Assembly-CSharp/StatsPopup.cs32
-rw-r--r--Client/Assembly-CSharp/SteamBehaviour.cs35
-rw-r--r--Client/Assembly-CSharp/SteamManager.cs131
-rw-r--r--Client/Assembly-CSharp/SteamPurchasingModule.cs118
-rw-r--r--Client/Assembly-CSharp/StoreMenu.cs409
-rw-r--r--Client/Assembly-CSharp/StringExtensions.cs32
-rw-r--r--Client/Assembly-CSharp/StringNames.cs168
-rw-r--r--Client/Assembly-CSharp/StringOption.cs60
-rw-r--r--Client/Assembly-CSharp/SubString.cs77
-rw-r--r--Client/Assembly-CSharp/SubStringReader.cs51
-rw-r--r--Client/Assembly-CSharp/SurvCamera.cs28
-rw-r--r--Client/Assembly-CSharp/SurveillanceMinigame.cs140
-rw-r--r--Client/Assembly-CSharp/SweepMinigame.cs123
-rw-r--r--Client/Assembly-CSharp/SwitchMinigame.cs97
-rw-r--r--Client/Assembly-CSharp/SwitchSystem.cs107
-rw-r--r--Client/Assembly-CSharp/SystemConsole.cs77
-rw-r--r--Client/Assembly-CSharp/SystemTypeHelpers.cs7
-rw-r--r--Client/Assembly-CSharp/SystemTypes.cs30
-rw-r--r--Client/Assembly-CSharp/TabButton.cs10
-rw-r--r--Client/Assembly-CSharp/TabGroup.cs25
-rw-r--r--Client/Assembly-CSharp/TaskAddButton.cs109
-rw-r--r--Client/Assembly-CSharp/TaskAdderGame.cs168
-rw-r--r--Client/Assembly-CSharp/TaskFolder.cs31
-rw-r--r--Client/Assembly-CSharp/TaskPanelBehaviour.cs52
-rw-r--r--Client/Assembly-CSharp/TaskSet.cs9
-rw-r--r--Client/Assembly-CSharp/TaskTypes.cs31
-rw-r--r--Client/Assembly-CSharp/TaskTypesHelpers.cs7
-rw-r--r--Client/Assembly-CSharp/TempData.cs74
-rw-r--r--Client/Assembly-CSharp/TextBox.cs257
-rw-r--r--Client/Assembly-CSharp/TextController.cs130
-rw-r--r--Client/Assembly-CSharp/TextLink.cs26
-rw-r--r--Client/Assembly-CSharp/TextRenderer.cs482
-rw-r--r--Client/Assembly-CSharp/TextTranslator.cs24
-rw-r--r--Client/Assembly-CSharp/ToggleButtonBehaviour.cs42
-rw-r--r--Client/Assembly-CSharp/ToggleOption.cs45
-rw-r--r--Client/Assembly-CSharp/TowerBehaviour.cs43
-rw-r--r--Client/Assembly-CSharp/TransitionOpen.cs54
-rw-r--r--Client/Assembly-CSharp/TransitionType.cs7
-rw-r--r--Client/Assembly-CSharp/TranslatedImageSet.cs8
-rw-r--r--Client/Assembly-CSharp/TranslationController.cs70
-rw-r--r--Client/Assembly-CSharp/TumbleBoxBehaviour.cs24
-rw-r--r--Client/Assembly-CSharp/TuneRadioMinigame.cs104
-rw-r--r--Client/Assembly-CSharp/TutorialManager.cs63
-rw-r--r--Client/Assembly-CSharp/TutorialStatsManager.cs12
-rw-r--r--Client/Assembly-CSharp/TwitterLink.cs12
-rw-r--r--Client/Assembly-CSharp/UnlockManifoldsMinigame.cs100
-rw-r--r--Client/Assembly-CSharp/UnlockPopUp.cs22
-rw-r--r--Client/Assembly-CSharp/UploadDataGame.cs203
-rw-r--r--Client/Assembly-CSharp/UploadDataTask.cs34
-rw-r--r--Client/Assembly-CSharp/UseButtonManager.cs108
-rw-r--r--Client/Assembly-CSharp/Vector2Range.cs55
-rw-r--r--Client/Assembly-CSharp/VendingMinigame.cs188
-rw-r--r--Client/Assembly-CSharp/VendingSlot.cs37
-rw-r--r--Client/Assembly-CSharp/Vent.cs163
-rw-r--r--Client/Assembly-CSharp/VersionShower.cs19
-rw-r--r--Client/Assembly-CSharp/VerticalGauge.cs28
-rw-r--r--Client/Assembly-CSharp/VirtualJoystick.cs59
-rw-r--r--Client/Assembly-CSharp/VoteBanSystem.cs111
-rw-r--r--Client/Assembly-CSharp/WaitForHostPopup.cs27
-rw-r--r--Client/Assembly-CSharp/WaitForLerp.cs38
-rw-r--r--Client/Assembly-CSharp/WeaponsMinigame.cs149
-rw-r--r--Client/Assembly-CSharp/WeatherMinigame.cs34
-rw-r--r--Client/Assembly-CSharp/WinningPlayerData.cs36
-rw-r--r--Client/Assembly-CSharp/Wire.cs61
-rw-r--r--Client/Assembly-CSharp/WireMinigame.cs157
-rw-r--r--Client/Assembly-CSharp/WireNode.cs19
-rw-r--r--Client/Assembly-CSharp/XXHash.cs189
-rw-r--r--Client/Assembly-CSharp/obj/Debug/Assembly-CSharp.csproj.CoreCompileInputs.cache1
-rw-r--r--Client/Assembly-CSharp/obj/Debug/Assembly-CSharp.csprojAssemblyReference.cachebin0 -> 44249 bytes
381 files changed, 37356 insertions, 0 deletions
diff --git a/Client/Assembly-CSharp/AcceptDivertPowerGame.cs b/Client/Assembly-CSharp/AcceptDivertPowerGame.cs
new file mode 100644
index 0000000..14867f1
--- /dev/null
+++ b/Client/Assembly-CSharp/AcceptDivertPowerGame.cs
@@ -0,0 +1,84 @@
+using System;
+using System.Collections;
+using UnityEngine;
+
+public class AcceptDivertPowerGame : Minigame
+{
+ private LineRenderer[] LeftWires;
+
+ private LineRenderer[] RightWires;
+
+ public GameObject RightWireParent;
+
+ public GameObject LeftWireParent;
+
+ public SpriteRenderer Switch;
+
+ public AudioClip SwitchSound;
+
+ private bool done;
+
+ public void Start()
+ {
+ this.LeftWires = this.LeftWireParent.GetComponentsInChildren<LineRenderer>();
+ this.RightWires = this.RightWireParent.GetComponentsInChildren<LineRenderer>();
+ for (int i = 0; i < this.LeftWires.Length; i++)
+ {
+ this.LeftWires[i].material.SetColor("_Color", Color.yellow);
+ }
+ }
+
+ public void DoSwitch()
+ {
+ if (this.done)
+ {
+ return;
+ }
+ this.done = true;
+ if (Constants.ShouldPlaySfx())
+ {
+ SoundManager.Instance.PlaySound(this.SwitchSound, false, 1f);
+ }
+ base.StartCoroutine(this.CoDoSwitch());
+ }
+
+ private IEnumerator CoDoSwitch()
+ {
+ yield return new WaitForLerp(0.25f, delegate(float t)
+ {
+ this.Switch.transform.localEulerAngles = new Vector3(0f, 0f, Mathf.Lerp(0f, 90f, t));
+ });
+ this.LeftWires[0].SetPosition(1, new Vector3(1.265f, 0f, 0f));
+ for (int i = 0; i < this.RightWires.Length; i++)
+ {
+ this.RightWires[i].enabled = true;
+ this.RightWires[i].material.SetColor("_Color", Color.yellow);
+ }
+ for (int j = 0; j < this.LeftWires.Length; j++)
+ {
+ this.LeftWires[j].material.SetColor("_Color", Color.yellow);
+ }
+ if (this.MyNormTask)
+ {
+ this.MyNormTask.NextStep();
+ }
+ base.StartCoroutine(base.CoStartClose(0.75f));
+ yield break;
+ }
+
+ public void Update()
+ {
+ for (int i = 0; i < this.LeftWires.Length; i++)
+ {
+ Vector2 textureOffset = this.LeftWires[i].material.GetTextureOffset("_MainTex");
+ textureOffset.x -= Time.fixedDeltaTime * 3f;
+ this.LeftWires[i].material.SetTextureOffset("_MainTex", textureOffset);
+ }
+ for (int j = 0; j < this.RightWires.Length; j++)
+ {
+ Vector2 textureOffset2 = this.RightWires[j].material.GetTextureOffset("_MainTex");
+ textureOffset2.x += Time.fixedDeltaTime * 3f;
+ this.RightWires[j].material.SetTextureOffset("_MainTex", textureOffset2);
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/AdDataCollectScreen.cs b/Client/Assembly-CSharp/AdDataCollectScreen.cs
new file mode 100644
index 0000000..35212f6
--- /dev/null
+++ b/Client/Assembly-CSharp/AdDataCollectScreen.cs
@@ -0,0 +1,65 @@
+using System;
+using System.Collections;
+using UnityEngine;
+
+public class AdDataCollectScreen : MonoBehaviour
+{
+ public ToggleButtonBehaviour PersonalizedAdsButton;
+
+ private void Start()
+ {
+ this.UpdateButtons();
+ }
+
+ public IEnumerator Show()
+ {
+ if (!SaveManager.ShowAdsScreen.HasFlag(ShowAdsState.Accepted) && !SaveManager.BoughtNoAds)
+ {
+ base.gameObject.SetActive(true);
+ while (base.gameObject.activeSelf)
+ {
+ yield return null;
+ }
+ }
+ yield break;
+ }
+
+ public void Close()
+ {
+ SaveManager.ShowAdsScreen |= ShowAdsState.Accepted;
+ }
+
+ public void Update()
+ {
+ if (SaveManager.BoughtNoAds)
+ {
+ base.GetComponent<TransitionOpen>().Close();
+ }
+ }
+
+ public void TogglePersonalizedAd()
+ {
+ ShowAdsState showAdsState = SaveManager.ShowAdsScreen & (ShowAdsState)127;
+ if (showAdsState != ShowAdsState.Personalized)
+ {
+ if (showAdsState == ShowAdsState.NonPersonalized)
+ {
+ SaveManager.ShowAdsScreen = ShowAdsState.Personalized;
+ goto IL_34;
+ }
+ if (showAdsState == ShowAdsState.Purchased)
+ {
+ SaveManager.ShowAdsScreen = ShowAdsState.Purchased;
+ goto IL_34;
+ }
+ }
+ SaveManager.ShowAdsScreen = ShowAdsState.NonPersonalized;
+ IL_34:
+ this.UpdateButtons();
+ }
+
+ public void UpdateButtons()
+ {
+ this.PersonalizedAdsButton.UpdateText(!SaveManager.ShowAdsScreen.HasFlag(ShowAdsState.NonPersonalized));
+ }
+}
diff --git a/Client/Assembly-CSharp/AdPlayer.cs b/Client/Assembly-CSharp/AdPlayer.cs
new file mode 100644
index 0000000..92ab040
--- /dev/null
+++ b/Client/Assembly-CSharp/AdPlayer.cs
@@ -0,0 +1,118 @@
+using System;
+using System.Collections;
+using GoogleMobileAds.Api;
+using InnerNet;
+using UnityEngine;
+
+public static class AdPlayer
+{
+ private static InterstitialAd interstitial;
+
+ private const string appId = "unexpected_platform";
+
+ private const string adUnitId = "unexpected_platform";
+
+ public static void ShowInterstitial(MonoBehaviour parent, bool playAgain)
+ {
+ parent.StartCoroutine(AdPlayer.CoShowAd(playAgain));
+ }
+
+ private static IEnumerator CoShowAd(bool playAgain)
+ {
+ if (playAgain)
+ {
+ yield return DestroyableSingleton<EndGameManager>.Instance.CoJoinGame();
+ }
+ else
+ {
+ AmongUsClient.Instance.ExitGame(DisconnectReasons.ExitGame);
+ }
+ yield break;
+ }
+
+ public static void RequestInterstitial()
+ {
+ try
+ {
+ MobileAds.Initialize("unexpected_platform");
+ if (AdPlayer.interstitial == null)
+ {
+ AdPlayer.interstitial = new InterstitialAd("unexpected_platform");
+ AdRequest adRequest = new AdRequest.Builder().Build();
+ if (SaveManager.ShowAdsScreen.HasFlag(ShowAdsState.NonPersonalized))
+ {
+ adRequest.Extras.Add("npa", "1");
+ }
+ AdPlayer.interstitial.OnAdLoaded += AdPlayer.Interstitial_OnAdLoaded;
+ AdPlayer.interstitial.OnAdFailedToLoad += AdPlayer.Interstitial_OnAdFailedToLoad;
+ AdPlayer.interstitial.OnAdClosed += AdPlayer.Interstitial_OnAdClosed;
+ AdPlayer.interstitial.OnAdLeavingApplication += AdPlayer.Interstitial_OnAdLeavingApplication;
+ AdPlayer.interstitial.LoadAd(adRequest);
+ }
+ }
+ catch
+ {
+ try
+ {
+ if (AdPlayer.interstitial != null)
+ {
+ AdPlayer.interstitial.Destroy();
+ }
+ }
+ catch
+ {
+ }
+ AdPlayer.interstitial = null;
+ }
+ }
+
+ private static void Interstitial_OnAdLoaded(object sender, EventArgs e)
+ {
+ }
+
+ private static void Interstitial_OnAdLeavingApplication(object sender, EventArgs e)
+ {
+ try
+ {
+ if (AdPlayer.interstitial != null)
+ {
+ AdPlayer.interstitial.Destroy();
+ }
+ }
+ finally
+ {
+ AdPlayer.interstitial = null;
+ }
+ }
+
+ private static void Interstitial_OnAdFailedToLoad(object sender, AdFailedToLoadEventArgs e)
+ {
+ try
+ {
+ if (AdPlayer.interstitial != null)
+ {
+ AdPlayer.interstitial.Destroy();
+ Debug.LogError("Couldn't load ad: " + (e.Message ?? "No Message"));
+ }
+ }
+ finally
+ {
+ AdPlayer.interstitial = null;
+ }
+ }
+
+ private static void Interstitial_OnAdClosed(object sender, EventArgs e)
+ {
+ try
+ {
+ if (AdPlayer.interstitial != null)
+ {
+ AdPlayer.interstitial.Destroy();
+ }
+ }
+ finally
+ {
+ AdPlayer.interstitial = null;
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/AlignGame.cs b/Client/Assembly-CSharp/AlignGame.cs
new file mode 100644
index 0000000..1ee70f0
--- /dev/null
+++ b/Client/Assembly-CSharp/AlignGame.cs
@@ -0,0 +1,146 @@
+using System;
+using System.Collections;
+using UnityEngine;
+
+public class AlignGame : Minigame
+{
+ private Controller myController = new Controller();
+
+ public FloatRange YRange = new FloatRange(-0.425f, 0.425f);
+
+ public AnimationCurve curve;
+
+ public LineRenderer centerline;
+
+ public LineRenderer[] guidelines;
+
+ public SpriteRenderer engine;
+
+ public Collider2D col;
+
+ public TextController StatusText;
+
+ private float pulseTimer;
+
+ public override void Begin(PlayerTask task)
+ {
+ base.Begin(task);
+ float value = AlignGame.FromByte(this.MyNormTask.Data[base.ConsoleId]);
+ bool flag = AlignGame.IsSuccess(this.MyNormTask.Data[base.ConsoleId]);
+ Vector3 localPosition = this.col.transform.localPosition;
+ localPosition.y = this.YRange.Clamp(value);
+ float num = this.YRange.ReverseLerp(localPosition.y);
+ localPosition.x = this.curve.Evaluate(num);
+ this.col.transform.eulerAngles = new Vector3(0f, 0f, Mathf.Lerp(20f, -20f, num));
+ this.engine.transform.eulerAngles = new Vector3(0f, 0f, Mathf.Lerp(45f, -45f, num));
+ this.centerline.material.SetColor("_Color", flag ? Color.green : Color.red);
+ this.engine.color = (flag ? Color.green : Color.red);
+ this.col.transform.localPosition = localPosition;
+ this.guidelines[0].enabled = flag;
+ this.guidelines[1].enabled = flag;
+ this.StatusText.gameObject.SetActive(flag);
+ }
+
+ public void Update()
+ {
+ this.centerline.material.SetTextureOffset("_MainTex", new Vector2(Time.time, 0f));
+ this.guidelines[0].material.SetTextureOffset("_MainTex", new Vector2(Time.time, 0f));
+ this.guidelines[1].material.SetTextureOffset("_MainTex", new Vector2(Time.time, 0f));
+ if (this.MyTask && this.MyNormTask.IsComplete)
+ {
+ return;
+ }
+ Vector3 localPosition = this.col.transform.localPosition;
+ bool flag = AlignGame.IsSuccess(this.MyNormTask.Data[base.ConsoleId]);
+ bool flag2 = AlignGame.IsSuccess(AlignGame.ToByte(localPosition.y));
+ this.myController.Update();
+ switch (this.myController.CheckDrag(this.col, false))
+ {
+ case DragState.TouchStart:
+ this.pulseTimer = 0f;
+ break;
+ case DragState.Dragging:
+ if (!flag)
+ {
+ Vector2 vector = this.myController.DragPosition - base.transform.position;
+ float num = this.YRange.ReverseLerp(localPosition.y);
+ localPosition.y = this.YRange.Clamp(vector.y);
+ float num2 = this.YRange.ReverseLerp(localPosition.y);
+ localPosition.x = this.curve.Evaluate(num2);
+ this.col.transform.eulerAngles = new Vector3(0f, 0f, Mathf.Lerp(20f, -20f, num2));
+ this.engine.transform.eulerAngles = new Vector3(0f, 0f, Mathf.Lerp(45f, -45f, num2));
+ this.centerline.material.SetColor("_Color", flag2 ? Color.green : Color.red);
+ if (Mathf.Abs(num2 - num) > 0.001f)
+ {
+ this.pulseTimer += Time.deltaTime * 25f;
+ int num3 = (int)this.pulseTimer % 3;
+ if (num3 > 1)
+ {
+ if (num3 == 2)
+ {
+ this.engine.color = Color.clear;
+ }
+ }
+ else
+ {
+ this.engine.color = Color.red;
+ }
+ }
+ else
+ {
+ this.engine.color = Color.red;
+ }
+ }
+ break;
+ case DragState.Released:
+ if (!flag && flag2)
+ {
+ base.StartCoroutine(this.LockEngine());
+ this.MyNormTask.Data[base.ConsoleId] = AlignGame.ToByte(localPosition.y);
+ this.MyNormTask.NextStep();
+ base.StartCoroutine(base.CoStartClose(0.75f));
+ }
+ break;
+ }
+ this.col.transform.localPosition = localPosition;
+ }
+
+ private IEnumerator LockEngine()
+ {
+ int num;
+ for (int i = 0; i < 3; i = num)
+ {
+ this.guidelines[0].enabled = true;
+ this.guidelines[1].enabled = true;
+ yield return new WaitForSeconds(0.1f);
+ this.guidelines[0].enabled = false;
+ this.guidelines[1].enabled = false;
+ yield return new WaitForSeconds(0.1f);
+ num = i + 1;
+ }
+ this.StatusText.gameObject.SetActive(true);
+ Color green = new Color(0f, 0.7f, 0f);
+ yield return new WaitForLerp(1f, delegate(float t)
+ {
+ this.engine.color = Color.Lerp(Color.white, green, t);
+ });
+ this.guidelines[0].enabled = true;
+ this.guidelines[1].enabled = true;
+ yield break;
+ }
+
+ public static float FromByte(byte b)
+ {
+ return (float)b * 0.025f - 3f;
+ }
+
+ public static byte ToByte(float y)
+ {
+ return (byte)((y + 3f) / 0.025f);
+ }
+
+ public static bool IsSuccess(byte b)
+ {
+ return Mathf.Abs(AlignGame.FromByte(b)) <= 0.05f;
+ }
+}
diff --git a/Client/Assembly-CSharp/AlphaBlink.cs b/Client/Assembly-CSharp/AlphaBlink.cs
new file mode 100644
index 0000000..4813ba6
--- /dev/null
+++ b/Client/Assembly-CSharp/AlphaBlink.cs
@@ -0,0 +1,44 @@
+using System;
+using UnityEngine;
+
+public class AlphaBlink : MonoBehaviour
+{
+ public float Period = 1f;
+
+ public float Ratio = 0.5f;
+
+ private SpriteRenderer rend;
+
+ private MeshRenderer mesh;
+
+ public FloatRange AlphaRange = new FloatRange(0.2f, 0.5f);
+
+ public Color baseColor = Color.white;
+
+ public void SetColor(Color c)
+ {
+ this.Start();
+ this.baseColor = c;
+ this.Update();
+ }
+
+ private void Start()
+ {
+ this.mesh = base.GetComponent<MeshRenderer>();
+ this.rend = base.GetComponent<SpriteRenderer>();
+ }
+
+ public void Update()
+ {
+ float num = Time.time % this.Period / this.Period;
+ num = (float)((num < this.Ratio) ? 1 : 0);
+ if (this.rend)
+ {
+ this.rend.color = new Color(this.baseColor.r, this.baseColor.g, this.baseColor.b, this.AlphaRange.Lerp(num));
+ }
+ if (this.mesh)
+ {
+ this.mesh.material.SetColor("_Color", new Color(this.baseColor.r, this.baseColor.g, this.baseColor.b, this.AlphaRange.Lerp(num)));
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/AlphaPulse.cs b/Client/Assembly-CSharp/AlphaPulse.cs
new file mode 100644
index 0000000..e28579e
--- /dev/null
+++ b/Client/Assembly-CSharp/AlphaPulse.cs
@@ -0,0 +1,43 @@
+using System;
+using UnityEngine;
+
+public class AlphaPulse : MonoBehaviour
+{
+ public float Offset = 1f;
+
+ public float Duration = 2.5f;
+
+ private SpriteRenderer rend;
+
+ private MeshRenderer mesh;
+
+ public FloatRange AlphaRange = new FloatRange(0.2f, 0.5f);
+
+ public Color baseColor = Color.white;
+
+ public void SetColor(Color c)
+ {
+ this.Start();
+ this.baseColor = c;
+ this.Update();
+ }
+
+ private void Start()
+ {
+ this.mesh = base.GetComponent<MeshRenderer>();
+ this.rend = base.GetComponent<SpriteRenderer>();
+ }
+
+ public void Update()
+ {
+ float v = Mathf.Abs(Mathf.Cos((this.Offset + Time.time) * 3.1415927f / this.Duration));
+ if (this.rend)
+ {
+ this.rend.color = new Color(this.baseColor.r, this.baseColor.g, this.baseColor.b, this.AlphaRange.Lerp(v));
+ }
+ if (this.mesh)
+ {
+ this.mesh.material.SetColor("_Color", new Color(this.baseColor.r, this.baseColor.g, this.baseColor.b, this.AlphaRange.Lerp(v)));
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/AmongUsClient.cs b/Client/Assembly-CSharp/AmongUsClient.cs
new file mode 100644
index 0000000..5726992
--- /dev/null
+++ b/Client/Assembly-CSharp/AmongUsClient.cs
@@ -0,0 +1,497 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using Assets.CoreScripts;
+using InnerNet;
+using UnityEngine;
+using UnityEngine.SceneManagement;
+
+public class AmongUsClient : InnerNetClient
+{
+ public static AmongUsClient Instance;
+
+ public GameModes GameMode;
+
+ public string OnlineScene;
+
+ public string MainMenuScene;
+
+ public GameData GameDataPrefab;
+
+ public PlayerControl PlayerPrefab;
+
+ public List<ShipStatus> ShipPrefabs;
+
+ public float SpawnRadius = 1.75f;
+
+ public DiscoveryState discoverState;
+
+ public List<IDisconnectHandler> DisconnectHandlers = new List<IDisconnectHandler>();
+
+ public List<IGameListHandler> GameListHandlers = new List<IGameListHandler>();
+
+ public void Awake()
+ {
+ if (AmongUsClient.Instance)
+ {
+ if (AmongUsClient.Instance != this)
+ {
+ UnityEngine.Object.Destroy(base.gameObject);
+ }
+ return;
+ }
+ AmongUsClient.Instance = this;
+ UnityEngine.Object.DontDestroyOnLoad(base.gameObject);
+ Application.targetFrameRate = 30;
+ }
+
+ protected override byte[] GetConnectionData()
+ {
+ byte[] result;
+ using (MemoryStream memoryStream = new MemoryStream())
+ {
+ using (BinaryWriter binaryWriter = new BinaryWriter(memoryStream))
+ {
+ binaryWriter.Write(Constants.GetBroadcastVersion());
+ binaryWriter.Write(SaveManager.PlayerName);
+ binaryWriter.Flush();
+ result = memoryStream.ToArray();
+ }
+ }
+ return result;
+ }
+
+ public void StartGame()
+ {
+ base.SendStartGame();
+ this.discoverState = DiscoveryState.Off;
+ }
+
+ public void ExitGame(DisconnectReasons reason = DisconnectReasons.ExitGame)
+ {
+ if (DestroyableSingleton<WaitForHostPopup>.InstanceExists)
+ {
+ DestroyableSingleton<WaitForHostPopup>.Instance.Hide();
+ }
+ SoundManager.Instance.StopAllSound();
+ this.discoverState = DiscoveryState.Off;
+ this.DisconnectHandlers.Clear();
+ base.DisconnectInternal(reason, null);
+ SceneManager.LoadScene(this.MainMenuScene);
+ }
+
+ protected override void OnGetGameList(int totalGames, List<GameListing> availableGames)
+ {
+ for (int i = 0; i < this.GameListHandlers.Count; i++)
+ {
+ try
+ {
+ this.GameListHandlers[i].HandleList(totalGames, availableGames);
+ }
+ catch
+ {
+ }
+ }
+ }
+
+ protected override void OnGameCreated(string gameIdString)
+ {
+ }
+
+ protected override void OnWaitForHost(string gameIdString)
+ {
+ if (this.GameState != InnerNetClient.GameStates.Joined)
+ {
+ Debug.Log("Waiting for host: " + gameIdString);
+ if (DestroyableSingleton<WaitForHostPopup>.InstanceExists)
+ {
+ DestroyableSingleton<WaitForHostPopup>.Instance.Show();
+ }
+ }
+ }
+
+ protected override void OnStartGame()
+ {
+ Debug.Log("Received game start: " + base.AmHost.ToString());
+ base.StartCoroutine(this.CoStartGame());
+ }
+
+ private IEnumerator CoStartGame()
+ {
+ yield return null;
+ while (!DestroyableSingleton<HudManager>.InstanceExists)
+ {
+ yield return null;
+ }
+ while (!PlayerControl.LocalPlayer)
+ {
+ yield return null;
+ }
+ PlayerControl.LocalPlayer.moveable = false;
+ CustomPlayerMenu customPlayerMenu = UnityEngine.Object.FindObjectOfType<CustomPlayerMenu>();
+ if (customPlayerMenu)
+ {
+ customPlayerMenu.Close(false);
+ }
+ if (DestroyableSingleton<GameStartManager>.InstanceExists)
+ {
+ this.DisconnectHandlers.Remove(DestroyableSingleton<GameStartManager>.Instance);
+ UnityEngine.Object.Destroy(DestroyableSingleton<GameStartManager>.Instance.gameObject);
+ }
+ if (DestroyableSingleton<DiscordManager>.InstanceExists)
+ {
+ DestroyableSingleton<DiscordManager>.Instance.SetPlayingGame();
+ }
+ yield return DestroyableSingleton<HudManager>.Instance.CoFadeFullScreen(Color.clear, Color.black, 0.2f);
+ while (!GameData.Instance)
+ {
+ yield return null;
+ }
+ while (!base.AmHost)
+ {
+ while (PlayerControl.LocalPlayer.Data == null && !base.AmHost)
+ {
+ yield return null;
+ }
+ if (!base.AmHost)
+ {
+ base.SendClientReady();
+ while (!ShipStatus.Instance && !base.AmHost)
+ {
+ yield return null;
+ }
+ if (!base.AmHost)
+ {
+ IL_324:
+ for (int i = 0; i < GameData.Instance.PlayerCount; i++)
+ {
+ PlayerControl @object = GameData.Instance.AllPlayers[i].Object;
+ if (@object)
+ {
+ @object.moveable = true;
+ @object.NetTransform.enabled = true;
+ @object.MyPhysics.enabled = true;
+ @object.MyPhysics.Awake();
+ @object.MyPhysics.ResetAnim(true);
+ @object.Collider.enabled = true;
+ Vector2 spawnLocation = ShipStatus.Instance.GetSpawnLocation(i, GameData.Instance.PlayerCount);
+ @object.NetTransform.SnapTo(spawnLocation);
+ }
+ }
+ yield break;
+ }
+ }
+ }
+ GameData.Instance.SetDirty();
+ base.SendClientReady();
+ float timer = 0f;
+ for (;;)
+ {
+ bool stopWaiting = true;
+ List<ClientData> allClients = this.allClients;
+ lock (allClients)
+ {
+ for (int j = 0; j < this.allClients.Count; j++)
+ {
+ ClientData clientData = this.allClients[j];
+ if (!clientData.IsReady)
+ {
+ if (timer < 5f)
+ {
+ stopWaiting = false;
+ }
+ else
+ {
+ base.SendLateRejection(clientData.Id, DisconnectReasons.Error);
+ clientData.IsReady = true;
+ this.OnPlayerLeft(clientData, DisconnectReasons.Error);
+ }
+ }
+ }
+ }
+ yield return null;
+ if (stopWaiting)
+ {
+ break;
+ }
+ timer += Time.deltaTime;
+ }
+ if (LobbyBehaviour.Instance)
+ {
+ LobbyBehaviour.Instance.Despawn();
+ }
+ if (!ShipStatus.Instance)
+ {
+ int index = Mathf.Clamp((int)PlayerControl.GameOptions.MapId, 0, this.ShipPrefabs.Count - 1);
+ ShipStatus.Instance = UnityEngine.Object.Instantiate<ShipStatus>(this.ShipPrefabs[index]);
+ }
+ base.Spawn(ShipStatus.Instance, -2, SpawnFlags.None);
+ ShipStatus.Instance.SelectInfected();
+ ShipStatus.Instance.Begin();
+ goto IL_324;
+ }
+
+ protected override void OnBecomeHost()
+ {
+ ClientData clientData = base.FindClientById(this.ClientId);
+ if (!clientData.Character)
+ {
+ this.OnGameJoined(null, clientData);
+ }
+ Debug.Log("Became Host");
+ base.RemoveUnownedObjects();
+ }
+
+ protected override void OnGameEnd(GameOverReason gameOverReason, bool showAd)
+ {
+ StatsManager.Instance.BanPoints -= 1.5f;
+ StatsManager.Instance.LastGameStarted = DateTime.MinValue;
+ this.DisconnectHandlers.Clear();
+ if (Minigame.Instance)
+ {
+ Minigame.Instance.Close();
+ Minigame.Instance.Close();
+ }
+ try
+ {
+ if (SaveManager.SendTelemetry)
+ {
+ DestroyableSingleton<Telemetry>.Instance.EndGame(gameOverReason);
+ }
+ }
+ catch
+ {
+ }
+ TempData.EndReason = gameOverReason;
+ TempData.showAd = showAd;
+ bool flag = TempData.DidHumansWin(gameOverReason);
+ TempData.winners = new List<WinningPlayerData>();
+ for (int i = 0; i < GameData.Instance.PlayerCount; i++)
+ {
+ GameData.PlayerInfo playerInfo = GameData.Instance.AllPlayers[i];
+ if (gameOverReason == GameOverReason.HumansDisconnect || gameOverReason == GameOverReason.ImpostorDisconnect || flag != playerInfo.IsImpostor)
+ {
+ TempData.winners.Add(new WinningPlayerData(playerInfo));
+ }
+ }
+ base.StartCoroutine(this.CoEndGame());
+ }
+
+ public IEnumerator CoEndGame()
+ {
+ yield return DestroyableSingleton<HudManager>.Instance.CoFadeFullScreen(Color.clear, Color.black, 0.5f);
+ SceneManager.LoadScene("EndGame");
+ yield break;
+ }
+
+ protected override void OnPlayerJoined(ClientData data)
+ {
+ if (DestroyableSingleton<GameStartManager>.InstanceExists)
+ {
+ DestroyableSingleton<GameStartManager>.Instance.ResetStartState();
+ }
+ if (base.AmHost && data.InScene)
+ {
+ this.CreatePlayer(data);
+ }
+ }
+
+ protected override void OnGameJoined(string gameIdString, ClientData data)
+ {
+ if (DestroyableSingleton<WaitForHostPopup>.InstanceExists)
+ {
+ DestroyableSingleton<WaitForHostPopup>.Instance.Hide();
+ }
+ if (!string.IsNullOrWhiteSpace(this.OnlineScene))
+ {
+ SceneManager.LoadScene(this.OnlineScene);
+ }
+ }
+
+ protected override void OnPlayerLeft(ClientData data, DisconnectReasons reason)
+ {
+ if (DestroyableSingleton<GameStartManager>.InstanceExists)
+ {
+ DestroyableSingleton<GameStartManager>.Instance.ResetStartState();
+ }
+ PlayerControl character = data.Character;
+ if (character)
+ {
+ for (int i = this.DisconnectHandlers.Count - 1; i > -1; i--)
+ {
+ try
+ {
+ this.DisconnectHandlers[i].HandleDisconnect(character, reason);
+ }
+ catch (Exception exception)
+ {
+ Debug.LogException(exception);
+ this.DisconnectHandlers.RemoveAt(i);
+ }
+ }
+ UnityEngine.Object.Destroy(character.gameObject);
+ }
+ else
+ {
+ Debug.LogWarning(string.Format("A player without a character disconnected: {0}: {1}", data.Id, data.InScene));
+ for (int j = this.DisconnectHandlers.Count - 1; j > -1; j--)
+ {
+ try
+ {
+ this.DisconnectHandlers[j].HandleDisconnect();
+ }
+ catch (Exception exception2)
+ {
+ Debug.LogException(exception2);
+ this.DisconnectHandlers.RemoveAt(j);
+ }
+ }
+ }
+ if (base.AmHost)
+ {
+ GameOptionsData gameOptions = PlayerControl.GameOptions;
+ if (gameOptions != null && gameOptions.isDefaults)
+ {
+ PlayerControl.GameOptions.SetRecommendations(GameData.Instance.PlayerCount, AmongUsClient.Instance.GameMode);
+ PlayerControl localPlayer = PlayerControl.LocalPlayer;
+ if (localPlayer != null)
+ {
+ localPlayer.RpcSyncSettings(PlayerControl.GameOptions);
+ }
+ }
+ }
+ base.RemoveUnownedObjects();
+ }
+
+ protected override void OnDisconnected()
+ {
+ SceneManager.LoadScene(this.MainMenuScene);
+ }
+
+ //c 切换场景
+ protected override void OnPlayerChangedScene(ClientData client, string currentScene)
+ {
+ client.InScene = true;
+ if (!base.AmHost)
+ {
+ return;
+ }
+ if (currentScene.Equals("Tutorial"))
+ {
+ GameData.Instance = UnityEngine.Object.Instantiate<GameData>(this.GameDataPrefab);
+ base.Spawn(GameData.Instance, -2, SpawnFlags.None);
+ base.Spawn(UnityEngine.Object.Instantiate<ShipStatus>(this.ShipPrefabs.Last<ShipStatus>()), -2, SpawnFlags.None);
+ this.CreatePlayer(client);
+ return;
+ }
+ if (currentScene.Equals("OnlineGame"))
+ {
+ if (client.Id != this.ClientId)
+ {
+ base.SendInitialData(client.Id);
+ }
+ else
+ {
+ if (this.GameMode == GameModes.LocalGame)
+ {
+ base.StartCoroutine(this.CoBroadcastManager());
+ }
+ if (!GameData.Instance)
+ {
+ GameData.Instance = UnityEngine.Object.Instantiate<GameData>(this.GameDataPrefab);
+ base.Spawn(GameData.Instance, -2, SpawnFlags.None);
+ }
+ }
+ this.CreatePlayer(client);
+ }
+ }
+
+ [ContextMenu("Spawn Tester")]
+ private void SpawnTester()
+ {
+ sbyte availableId = GameData.Instance.GetAvailableId();
+ Vector2 v = Vector2.up.Rotate((float)availableId * (360f / (float)Palette.PlayerColors.Length)) * this.SpawnRadius;
+ PlayerControl playerControl = UnityEngine.Object.Instantiate<PlayerControl>(this.PlayerPrefab, v, Quaternion.identity);
+ playerControl.PlayerId = (byte)availableId;
+ GameData.Instance.AddPlayer(playerControl);
+ base.Spawn(playerControl, -2, SpawnFlags.None);
+ playerControl.CmdCheckName("Test");
+ playerControl.CmdCheckColor(0);
+ if (DestroyableSingleton<HatManager>.InstanceExists)
+ {
+ playerControl.RpcSetHat((uint)((int)availableId % DestroyableSingleton<HatManager>.Instance.AllHats.Count));
+ playerControl.RpcSetSkin((uint)((int)availableId % DestroyableSingleton<HatManager>.Instance.AllSkins.Count));
+ playerControl.RpcSetPet((uint)availableId);
+ }
+ }
+
+ private void CreatePlayer(ClientData clientData)
+ {
+ if (clientData.Character)
+ {
+ return;
+ }
+ if (!base.AmHost)
+ {
+ Debug.Log("Waiting for host to make my player");
+ return;
+ }
+ if (!GameData.Instance)
+ {
+ GameData.Instance = UnityEngine.Object.Instantiate<GameData>(this.GameDataPrefab);
+ base.Spawn(GameData.Instance, -2, SpawnFlags.None);
+ }
+ sbyte availableId = GameData.Instance.GetAvailableId();
+ if (availableId == -1)
+ {
+ base.SendLateRejection(clientData.Id, DisconnectReasons.GameFull);
+ Debug.Log("Overfilled room.");
+ return;
+ }
+ Vector2 v = Vector2.zero;
+ if (ShipStatus.Instance)
+ {
+ v = ShipStatus.Instance.GetSpawnLocation((int)availableId, Palette.PlayerColors.Length);
+ }
+ else if (DestroyableSingleton<TutorialManager>.InstanceExists)
+ {
+ v = new Vector2(-1.9f, 3.25f);
+ }
+ Debug.Log(string.Format("Spawned player {0} for client {1}", availableId, clientData.Id));
+ PlayerControl playerControl = UnityEngine.Object.Instantiate<PlayerControl>(this.PlayerPrefab, v, Quaternion.identity);
+ playerControl.PlayerId = (byte)availableId;
+ clientData.Character = playerControl;
+ base.Spawn(playerControl, clientData.Id, SpawnFlags.IsClientCharacter);
+ GameData.Instance.AddPlayer(playerControl);
+ if (PlayerControl.GameOptions.isDefaults)
+ {
+ PlayerControl.GameOptions.SetRecommendations(GameData.Instance.PlayerCount, AmongUsClient.Instance.GameMode);
+ }
+ playerControl.RpcSyncSettings(PlayerControl.GameOptions);
+ }
+
+ private IEnumerator CoBroadcastManager()
+ {
+ while (!GameData.Instance)
+ {
+ yield return null;
+ }
+ int lastPlayerCount = 0;
+ this.discoverState = DiscoveryState.Broadcast;
+ while (this.discoverState == DiscoveryState.Broadcast)
+ {
+ if (lastPlayerCount != GameData.Instance.PlayerCount)
+ {
+ lastPlayerCount = GameData.Instance.PlayerCount;
+ string data = string.Format("{0}~Open~{1}~", SaveManager.PlayerName, GameData.Instance.PlayerCount);
+ DestroyableSingleton<InnerDiscover>.Instance.Interval = 1f;
+ DestroyableSingleton<InnerDiscover>.Instance.StartAsServer(data);
+ }
+ yield return null;
+ }
+ DestroyableSingleton<InnerDiscover>.Instance.StopServer();
+ yield break;
+ }
+}
diff --git a/Client/Assembly-CSharp/AmongUsProduct.cs b/Client/Assembly-CSharp/AmongUsProduct.cs
new file mode 100644
index 0000000..29e6d2d
--- /dev/null
+++ b/Client/Assembly-CSharp/AmongUsProduct.cs
@@ -0,0 +1,9 @@
+using System;
+
+[Serializable]
+public struct AmongUsProduct
+{
+ public string ProductId;
+
+ public HatBehaviour HatData;
+}
diff --git a/Client/Assembly-CSharp/Announcement.cs b/Client/Assembly-CSharp/Announcement.cs
new file mode 100644
index 0000000..25d3a48
--- /dev/null
+++ b/Client/Assembly-CSharp/Announcement.cs
@@ -0,0 +1,10 @@
+using System;
+
+public struct Announcement
+{
+ public int DateFetched;
+
+ public uint Id;
+
+ public string AnnounceText;
+}
diff --git a/Client/Assembly-CSharp/AnnouncementPopUp.cs b/Client/Assembly-CSharp/AnnouncementPopUp.cs
new file mode 100644
index 0000000..42b96b0
--- /dev/null
+++ b/Client/Assembly-CSharp/AnnouncementPopUp.cs
@@ -0,0 +1,154 @@
+using System;
+using System.Collections;
+using System.Net;
+using Hazel;
+using Hazel.Udp;
+using UnityEngine;
+
+public class AnnouncementPopUp : MonoBehaviour
+{
+ private const uint AnnouncementVersion = 1U;
+
+ private UdpClientConnection connection;
+
+ private static AnnouncementPopUp.AnnounceState AskedForUpdate;
+
+ public TextRenderer AnnounceText;
+
+ private Announcement announcementUpdate;
+
+ private enum AnnounceState
+ {
+ Fetching,
+ Failed,
+ Success,
+ Cached
+ }
+
+ private static bool IsSuccess(AnnouncementPopUp.AnnounceState state)
+ {
+ return state == AnnouncementPopUp.AnnounceState.Success || state == AnnouncementPopUp.AnnounceState.Cached;
+ }
+
+ public IEnumerator Init()
+ {
+ if (AnnouncementPopUp.AskedForUpdate != AnnouncementPopUp.AnnounceState.Fetching)
+ {
+ yield break;
+ }
+ yield return DestroyableSingleton<ServerManager>.Instance.WaitForServers();
+ this.connection = new UdpClientConnection(new IPEndPoint(IPAddress.Parse(DestroyableSingleton<ServerManager>.Instance.OnlineNetAddress), 22024), IPMode.IPv4);
+ this.connection.DataReceived += this.Connection_DataReceived;
+ this.connection.Disconnected += this.Connection_Disconnected;
+ Announcement lastAnnouncement = SaveManager.LastAnnouncement;
+ try
+ {
+ MessageWriter messageWriter = MessageWriter.Get(SendOption.None);
+ messageWriter.WritePacked(1U);
+ messageWriter.WritePacked(lastAnnouncement.Id);
+ this.connection.ConnectAsync(messageWriter.ToByteArray(true), 5000);
+ messageWriter.Recycle();
+ yield break;
+ }
+ catch
+ {
+ AnnouncementPopUp.AskedForUpdate = AnnouncementPopUp.AnnounceState.Failed;
+ yield break;
+ }
+ yield break;
+ }
+
+ private void Connection_Disconnected(object sender, DisconnectedEventArgs e)
+ {
+ AnnouncementPopUp.AskedForUpdate = AnnouncementPopUp.AnnounceState.Failed;
+ this.connection.Dispose();
+ this.connection = null;
+ }
+
+ private void Connection_DataReceived(DataReceivedEventArgs e)
+ {
+ MessageReader message = e.Message;
+ try
+ {
+ if (message.Length > 4)
+ {
+ this.announcementUpdate = default(Announcement);
+ this.announcementUpdate.DateFetched = DateTime.UtcNow.DayOfYear;
+ this.announcementUpdate.Id = message.ReadPackedUInt32();
+ this.announcementUpdate.AnnounceText = message.ReadString();
+ AnnouncementPopUp.AskedForUpdate = AnnouncementPopUp.AnnounceState.Success;
+ }
+ else
+ {
+ AnnouncementPopUp.AskedForUpdate = AnnouncementPopUp.AnnounceState.Cached;
+ }
+ }
+ finally
+ {
+ message.Recycle();
+ }
+ try
+ {
+ this.connection.Dispose();
+ this.connection = null;
+ }
+ catch
+ {
+ }
+ }
+
+ public IEnumerator Show()
+ {
+ float timer = 0f;
+ while (AnnouncementPopUp.AskedForUpdate == AnnouncementPopUp.AnnounceState.Fetching && this.connection != null && timer < 5f)
+ {
+ timer += Time.deltaTime;
+ yield return null;
+ }
+ if (!AnnouncementPopUp.IsSuccess(AnnouncementPopUp.AskedForUpdate))
+ {
+ Announcement lastAnnouncement = SaveManager.LastAnnouncement;
+ if (lastAnnouncement.Id == 0U)
+ {
+ this.AnnounceText.Text = "Couldn't get announcement.";
+ }
+ else
+ {
+ this.AnnounceText.Text = "Couldn't get announcement. Last Known:\r\n" + lastAnnouncement.AnnounceText;
+ }
+ }
+ else if (this.announcementUpdate.Id != SaveManager.LastAnnouncement.Id)
+ {
+ if (AnnouncementPopUp.AskedForUpdate != AnnouncementPopUp.AnnounceState.Cached)
+ {
+ base.gameObject.SetActive(true);
+ }
+ if (this.announcementUpdate.Id == 0U)
+ {
+ this.announcementUpdate = SaveManager.LastAnnouncement;
+ this.announcementUpdate.DateFetched = DateTime.UtcNow.DayOfYear;
+ }
+ SaveManager.LastAnnouncement = this.announcementUpdate;
+ this.AnnounceText.Text = this.announcementUpdate.AnnounceText;
+ }
+ while (base.gameObject.activeSelf)
+ {
+ yield return null;
+ }
+ yield break;
+ }
+
+ public void Close()
+ {
+ base.gameObject.SetActive(false);
+ }
+
+ private void OnDestroy()
+ {
+ if (this.connection != null)
+ {
+ this.connection.Dispose();
+ this.connection = null;
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/ArrowBehaviour.cs b/Client/Assembly-CSharp/ArrowBehaviour.cs
new file mode 100644
index 0000000..8e9365c
--- /dev/null
+++ b/Client/Assembly-CSharp/ArrowBehaviour.cs
@@ -0,0 +1,47 @@
+using System;
+using UnityEngine;
+
+public class ArrowBehaviour : MonoBehaviour
+{
+ public Vector3 target;
+
+ public float perc = 0.925f;
+
+ [HideInInspector]
+ public SpriteRenderer image;
+
+ public void Awake()
+ {
+ this.image = base.GetComponent<SpriteRenderer>();
+ }
+
+ public void Update()
+ {
+ Camera main = Camera.main;
+ Vector2 vector = this.target - main.transform.position;
+ float num = vector.magnitude / (main.orthographicSize * this.perc);
+ this.image.enabled = ((double)num > 0.3);
+ Vector2 vector2 = main.WorldToViewportPoint(this.target);
+ if (this.Between(vector2.x, 0f, 1f) && this.Between(vector2.y, 0f, 1f))
+ {
+ base.transform.position = this.target - vector.normalized * 0.6f;
+ float num2 = Mathf.Clamp(num, 0f, 1f);
+ base.transform.localScale = new Vector3(num2, num2, num2);
+ }
+ else
+ {
+ Vector2 vector3 = new Vector2(Mathf.Clamp(vector2.x * 2f - 1f, -1f, 1f), Mathf.Clamp(vector2.y * 2f - 1f, -1f, 1f));
+ float orthographicSize = main.orthographicSize;
+ float num3 = main.orthographicSize * main.aspect;
+ Vector3 b = new Vector3(Mathf.LerpUnclamped(0f, num3 * 0.88f, vector3.x), Mathf.LerpUnclamped(0f, orthographicSize * 0.79f, vector3.y), 0f);
+ base.transform.position = main.transform.position + b;
+ base.transform.localScale = Vector3.one;
+ }
+ base.transform.LookAt2d(this.target);
+ }
+
+ private bool Between(float value, float min, float max)
+ {
+ return value > min && value < max;
+ }
+}
diff --git a/Client/Assembly-CSharp/AspectPosition.cs b/Client/Assembly-CSharp/AspectPosition.cs
new file mode 100644
index 0000000..60654df
--- /dev/null
+++ b/Client/Assembly-CSharp/AspectPosition.cs
@@ -0,0 +1,86 @@
+using System;
+using UnityEngine;
+
+public class AspectPosition : MonoBehaviour
+{
+ public Camera parentCam;
+
+ private const int LeftFlag = 1;
+
+ private const int RightFlag = 2;
+
+ private const int BottomFlag = 4;
+
+ private const int TopFlag = 8;
+
+ public Vector3 DistanceFromEdge;
+
+ public AspectPosition.EdgeAlignments Alignment;
+
+ public enum EdgeAlignments
+ {
+ RightBottom = 6,
+ LeftBottom = 5,
+ RightTop = 10,
+ Left = 1,
+ Right,
+ Top = 8,
+ Bottom = 4,
+ LeftTop = 9
+ }
+
+ private void OnEnable()
+ {
+ this.AdjustPosition();
+ ResolutionManager.ResolutionChanged += this.AdjustPosition;
+ }
+
+ private void OnDisable()
+ {
+ ResolutionManager.ResolutionChanged -= this.AdjustPosition;
+ }
+
+ public void AdjustPosition()
+ {
+ Camera camera = this.parentCam ? this.parentCam : Camera.main;
+ float aspect = camera.aspect;
+ this.AdjustPosition(camera.aspect);
+ }
+
+ public void AdjustPosition(float aspect)
+ {
+ float orthographicSize = (this.parentCam ? this.parentCam : Camera.main).orthographicSize;
+ base.transform.localPosition = AspectPosition.ComputePosition(this.Alignment, this.DistanceFromEdge, orthographicSize, aspect);
+ }
+
+ public static Vector3 ComputePosition(AspectPosition.EdgeAlignments alignment, Vector3 relativePos)
+ {
+ Camera main = Camera.main;
+ float aspect = main.aspect;
+ float orthographicSize = main.orthographicSize;
+ return AspectPosition.ComputePosition(alignment, relativePos, orthographicSize, aspect);
+ }
+
+ public static Vector3 ComputePosition(AspectPosition.EdgeAlignments alignment, Vector3 relativePos, float cHeight, float aspect)
+ {
+ float num = cHeight * aspect;
+ Vector3 vector = relativePos;
+ if ((alignment & AspectPosition.EdgeAlignments.Left) != (AspectPosition.EdgeAlignments)0)
+ {
+ vector.x -= num;
+ }
+ else if ((alignment & AspectPosition.EdgeAlignments.Right) != (AspectPosition.EdgeAlignments)0)
+ {
+ vector.x = num - vector.x;
+ }
+ if ((alignment & AspectPosition.EdgeAlignments.Bottom) != (AspectPosition.EdgeAlignments)0)
+ {
+ vector.y -= cHeight;
+ }
+ else if ((alignment & AspectPosition.EdgeAlignments.Top) != (AspectPosition.EdgeAlignments)0)
+ {
+ vector.y = cHeight - vector.y;
+ }
+ return vector;
+ }
+}
diff --git a/Client/Assembly-CSharp/AspectSize.cs b/Client/Assembly-CSharp/AspectSize.cs
new file mode 100644
index 0000000..c0c8fe8
--- /dev/null
+++ b/Client/Assembly-CSharp/AspectSize.cs
@@ -0,0 +1,32 @@
+using System;
+using UnityEngine;
+
+public class AspectSize : MonoBehaviour
+{
+ public Sprite Background;
+
+ public SpriteRenderer Renderer;
+
+ public float PercentWidth = 0.95f;
+
+ public void OnEnable()
+ {
+ Camera main = Camera.main;
+ float num = main.orthographicSize * main.aspect;
+ float num2 = (this.Background ? this.Background : this.Renderer.sprite).bounds.size.x / 2f;
+ float num3 = num / num2 * this.PercentWidth;
+ if (num3 < 1f)
+ {
+ base.transform.localScale = new Vector3(num3, num3, num3);
+ }
+ }
+
+ public static float CalculateSize(Vector3 parentPos, Sprite sprite)
+ {
+ Camera main = Camera.main;
+ float num = main.orthographicSize * main.aspect + parentPos.x;
+ float x = sprite.bounds.size.x;
+ float b = num / x * 0.98f;
+ return Mathf.Min(1f, b);
+ }
+}
diff --git a/Client/Assembly-CSharp/Assembly-CSharp.csproj b/Client/Assembly-CSharp/Assembly-CSharp.csproj
new file mode 100644
index 0000000..a97f617
--- /dev/null
+++ b/Client/Assembly-CSharp/Assembly-CSharp.csproj
@@ -0,0 +1,464 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{4D37C17B-28D8-4D17-A439-F712A18E4C22}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <RootNamespace>Assembly-CSharp</RootNamespace>
+ <AssemblyName>Assembly-CSharp</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Assembly-CSharp-firstpass">
+ <HintPath>..\..\..\Program Files (x86)\Steam\steamapps\common\Among Us\Among Us_Data\Managed\Assembly-CSharp-firstpass.dll</HintPath>
+ </Reference>
+ <Reference Include="Hazel">
+ <HintPath>..\..\..\Program Files (x86)\Steam\steamapps\common\Among Us\Among Us_Data\Managed\Hazel.dll</HintPath>
+ </Reference>
+ <Reference Include="System">
+ <HintPath>..\..\..\Program Files (x86)\Steam\steamapps\common\Among Us\Among Us_Data\Managed\System.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Core">
+ <HintPath>..\..\..\Program Files (x86)\Steam\steamapps\common\Among Us\Among Us_Data\Managed\System.Core.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.AnimationModule">
+ <HintPath>..\..\..\Program Files (x86)\Steam\steamapps\common\Among Us\Among Us_Data\Managed\UnityEngine.AnimationModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.AudioModule">
+ <HintPath>..\..\..\Program Files (x86)\Steam\steamapps\common\Among Us\Among Us_Data\Managed\UnityEngine.AudioModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.CoreModule">
+ <HintPath>..\..\..\Program Files (x86)\Steam\steamapps\common\Among Us\Among Us_Data\Managed\UnityEngine.CoreModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.ImageConversionModule">
+ <HintPath>..\..\..\Program Files (x86)\Steam\steamapps\common\Among Us\Among Us_Data\Managed\UnityEngine.ImageConversionModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.ParticleSystemModule">
+ <HintPath>..\..\..\Program Files (x86)\Steam\steamapps\common\Among Us\Among Us_Data\Managed\UnityEngine.ParticleSystemModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.Physics2DModule">
+ <HintPath>..\..\..\Program Files (x86)\Steam\steamapps\common\Among Us\Among Us_Data\Managed\UnityEngine.Physics2DModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.Purchasing">
+ <HintPath>..\..\..\Program Files (x86)\Steam\steamapps\common\Among Us\Among Us_Data\Managed\UnityEngine.Purchasing.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.ScreenCaptureModule">
+ <HintPath>..\..\..\Program Files (x86)\Steam\steamapps\common\Among Us\Among Us_Data\Managed\UnityEngine.ScreenCaptureModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.SpriteMaskModule">
+ <HintPath>..\..\..\Program Files (x86)\Steam\steamapps\common\Among Us\Among Us_Data\Managed\UnityEngine.SpriteMaskModule.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.UI">
+ <HintPath>..\..\..\Program Files (x86)\Steam\steamapps\common\Among Us\Among Us_Data\Managed\UnityEngine.UI.dll</HintPath>
+ </Reference>
+ <Reference Include="UnityEngine.UnityAnalyticsModule">
+ <HintPath>..\..\..\Program Files (x86)\Steam\steamapps\common\Among Us\Among Us_Data\Managed\UnityEngine.UnityAnalyticsModule.dll</HintPath>
+ </Reference>
+ </ItemGroup>
+ <ItemGroup>
+ <AppDesigner Include="Properties\" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="AcceptDivertPowerGame.cs" />
+ <Compile Include="AdDataCollectScreen.cs" />
+ <Compile Include="AdPlayer.cs" />
+ <Compile Include="AlignGame.cs" />
+ <Compile Include="AlphaBlink.cs" />
+ <Compile Include="AlphaPulse.cs" />
+ <Compile Include="AmongUsClient.cs" />
+ <Compile Include="AmongUsProduct.cs" />
+ <Compile Include="Announcement.cs" />
+ <Compile Include="AnnouncementPopUp.cs" />
+ <Compile Include="ArrowBehaviour.cs" />
+ <Compile Include="AspectPosition.cs" />
+ <Compile Include="AspectSize.cs" />
+ <Compile Include="Assets\CoreScripts\Telemetry.cs" />
+ <Compile Include="Asteroid.cs" />
+ <Compile Include="AutoOpenDoor.cs" />
+ <Compile Include="BanButton.cs" />
+ <Compile Include="BanMenu.cs" />
+ <Compile Include="BlockedWords.cs" />
+ <Compile Include="BoolRange.cs" />
+ <Compile Include="ButtonBehavior.cs" />
+ <Compile Include="ButtonRolloverHandler.cs" />
+ <Compile Include="CardSlideGame.cs" />
+ <Compile Include="ChainBehaviour.cs" />
+ <Compile Include="ChatBubble.cs" />
+ <Compile Include="ChatController.cs" />
+ <Compile Include="ChatNoteTypes.cs" />
+ <Compile Include="CloudGenerator.cs" />
+ <Compile Include="ColorChip.cs" />
+ <Compile Include="ConditionalHide.cs" />
+ <Compile Include="ConditionalStore.cs" />
+ <Compile Include="Console.cs" />
+ <Compile Include="Constants.cs" />
+ <Compile Include="Controller.cs" />
+ <Compile Include="CooldownHelpers.cs" />
+ <Compile Include="CounterArea.cs" />
+ <Compile Include="CourseMinigame.cs" />
+ <Compile Include="CourseStarBehaviour.cs" />
+ <Compile Include="CreateGameOptions.cs" />
+ <Compile Include="CreateOptionsPicker.cs" />
+ <Compile Include="CreateStoreButton.cs" />
+ <Compile Include="CrewVisualizer.cs" />
+ <Compile Include="CrossFadeImages.cs" />
+ <Compile Include="CrossFader.cs" />
+ <Compile Include="CrystalBehaviour.cs" />
+ <Compile Include="CrystalMinigame.cs" />
+ <Compile Include="CustomNetworkTransform.cs" />
+ <Compile Include="CustomPlayerMenu.cs" />
+ <Compile Include="DataCollectScreen.cs" />
+ <Compile Include="DeadBody.cs" />
+ <Compile Include="DeathReason.cs" />
+ <Compile Include="DeconSystem.cs" />
+ <Compile Include="DefaultPool.cs" />
+ <Compile Include="DemoKeyboardStick.cs" />
+ <Compile Include="DestroyableSingleton.cs" />
+ <Compile Include="DialBehaviour.cs" />
+ <Compile Include="DialogueBox.cs" />
+ <Compile Include="DisconnectPopup.cs" />
+ <Compile Include="DiscordManager.cs" />
+ <Compile Include="DiscoveryState.cs" />
+ <Compile Include="DiscussBehaviour.cs" />
+ <Compile Include="DivertPowerMetagame.cs" />
+ <Compile Include="DivertPowerMinigame.cs" />
+ <Compile Include="DivertPowerTask.cs" />
+ <Compile Include="DoorsSystemType.cs" />
+ <Compile Include="DotAligner.cs" />
+ <Compile Include="DragState.cs" />
+ <Compile Include="DummyBehaviour.cs" />
+ <Compile Include="DummyConsole.cs" />
+ <Compile Include="DynamicSound.cs" />
+ <Compile Include="Effects.cs" />
+ <Compile Include="ElectricTask.cs" />
+ <Compile Include="EmergencyMinigame.cs" />
+ <Compile Include="EmptyGarbageMinigame.cs" />
+ <Compile Include="EndGameManager.cs" />
+ <Compile Include="EngineBehaviour.cs" />
+ <Compile Include="EnterCodeMinigame.cs" />
+ <Compile Include="ExileController.cs" />
+ <Compile Include="ExitGameButton.cs" />
+ <Compile Include="Extensions.cs" />
+ <Compile Include="FindAGameManager.cs" />
+ <Compile Include="FindGameButton.cs" />
+ <Compile Include="FingerBehaviour.cs" />
+ <Compile Include="FixedActionConsole.cs" />
+ <Compile Include="FlatWaveBehaviour.cs" />
+ <Compile Include="FloatRange.cs" />
+ <Compile Include="FollowerCamera.cs" />
+ <Compile Include="FontCache.cs" />
+ <Compile Include="FontData.cs" />
+ <Compile Include="FontExtensionData.cs" />
+ <Compile Include="FontLoader.cs" />
+ <Compile Include="GameData.cs" />
+ <Compile Include="GameDiscovery.cs" />
+ <Compile Include="GameModes.cs" />
+ <Compile Include="GameObjectExtensions.cs" />
+ <Compile Include="GameOptionsData.cs" />
+ <Compile Include="GameOptionsMenu.cs" />
+ <Compile Include="GameOverReason.cs" />
+ <Compile Include="GameSettingMenu.cs" />
+ <Compile Include="GameStartManager.cs" />
+ <Compile Include="GarbageBehaviour.cs" />
+ <Compile Include="GoogleMobileAds\Api\AdapterState.cs" />
+ <Compile Include="GoogleMobileAds\Api\AdapterStatus.cs" />
+ <Compile Include="GoogleMobileAds\Api\AdErrorEventArgs.cs" />
+ <Compile Include="GoogleMobileAds\Api\AdFailedToLoadEventArgs.cs" />
+ <Compile Include="GoogleMobileAds\Api\AdLoader.cs" />
+ <Compile Include="GoogleMobileAds\Api\AdPosition.cs" />
+ <Compile Include="GoogleMobileAds\Api\AdRequest.cs" />
+ <Compile Include="GoogleMobileAds\Api\AdSize.cs" />
+ <Compile Include="GoogleMobileAds\Api\BannerView.cs" />
+ <Compile Include="GoogleMobileAds\Api\CustomNativeEventArgs.cs" />
+ <Compile Include="GoogleMobileAds\Api\CustomNativeTemplateAd.cs" />
+ <Compile Include="GoogleMobileAds\Api\Gender.cs" />
+ <Compile Include="GoogleMobileAds\Api\InterstitialAd.cs" />
+ <Compile Include="GoogleMobileAds\Api\Mediation\MediationExtras.cs" />
+ <Compile Include="GoogleMobileAds\Api\MobileAds.cs" />
+ <Compile Include="GoogleMobileAds\Api\NativeAdType.cs" />
+ <Compile Include="GoogleMobileAds\Api\Reward.cs" />
+ <Compile Include="GoogleMobileAds\Api\RewardBasedVideoAd.cs" />
+ <Compile Include="GoogleMobileAds\Api\RewardedAd.cs" />
+ <Compile Include="GoogleMobileAds\Api\ServerSideVerificationOptions.cs" />
+ <Compile Include="GoogleMobileAds\Common\DummyClient.cs" />
+ <Compile Include="GoogleMobileAds\Common\IAdLoaderClient.cs" />
+ <Compile Include="GoogleMobileAds\Common\IBannerClient.cs" />
+ <Compile Include="GoogleMobileAds\Common\ICustomNativeTemplateClient.cs" />
+ <Compile Include="GoogleMobileAds\Common\IInterstitialClient.cs" />
+ <Compile Include="GoogleMobileAds\Common\IMobileAdsClient.cs" />
+ <Compile Include="GoogleMobileAds\Common\IRewardBasedVideoAdClient.cs" />
+ <Compile Include="GoogleMobileAds\Common\IRewardedAdClient.cs" />
+ <Compile Include="GoogleMobileAds\Common\MobileAdsEventExecutor.cs" />
+ <Compile Include="GoogleMobileAds\Common\RewardedAdDummyClient.cs" />
+ <Compile Include="GoogleMobileAds\Common\Utils.cs" />
+ <Compile Include="GoogleMobileAds\GoogleMobileAdsClientFactory.cs" />
+ <Compile Include="HashRandom.cs" />
+ <Compile Include="HatBehaviour.cs" />
+ <Compile Include="HatManager.cs" />
+ <Compile Include="HatsTab.cs" />
+ <Compile Include="HorizontalGauge.cs" />
+ <Compile Include="HostGameButton.cs" />
+ <Compile Include="HowToPlayController.cs" />
+ <Compile Include="HudManager.cs" />
+ <Compile Include="HudOverrideSystemType.cs" />
+ <Compile Include="HudOverrideTask.cs" />
+ <Compile Include="IActivatable.cs" />
+ <Compile Include="IBuyable.cs" />
+ <Compile Include="IBytesSerializable.cs" />
+ <Compile Include="IConnectButton.cs" />
+ <Compile Include="IDisconnectHandler.cs" />
+ <Compile Include="IFocusHolder.cs" />
+ <Compile Include="IGameListHandler.cs" />
+ <Compile Include="ILocationActivate.cs" />
+ <Compile Include="ImageData.cs" />
+ <Compile Include="ImageNames.cs" />
+ <Compile Include="ImageTranslator.cs" />
+ <Compile Include="ImportantTextTask.cs" />
+ <Compile Include="InfectedOverlay.cs" />
+ <Compile Include="InnerNet\AlterGameTags.cs" />
+ <Compile Include="InnerNet\ClientData.cs" />
+ <Compile Include="InnerNet\DisconnectReasons.cs" />
+ <Compile Include="InnerNet\GameKeywords.cs" />
+ <Compile Include="InnerNet\GameListing.cs" />
+ <Compile Include="InnerNet\GameStates.cs" />
+ <Compile Include="InnerNet\InnerDiscover.cs" />
+ <Compile Include="InnerNet\InnerNetClient.cs" />
+ <Compile Include="InnerNet\InnerNetObject.cs" />
+ <Compile Include="InnerNet\InnerNetServer.cs" />
+ <Compile Include="InnerNet\JoinFailureReasons.cs" />
+ <Compile Include="InnerNet\LimboStates.cs" />
+ <Compile Include="InnerNet\MatchMakerModes.cs" />
+ <Compile Include="InnerNet\MessageExtensions.cs" />
+ <Compile Include="InnerNet\SpawnFlags.cs" />
+ <Compile Include="InnerNet\Tags.cs" />
+ <Compile Include="IntRange.cs" />
+ <Compile Include="IntroCutscene.cs" />
+ <Compile Include="IObjectPool.cs" />
+ <Compile Include="ISoundPlayer.cs" />
+ <Compile Include="ISystemType.cs" />
+ <Compile Include="ITranslatedText.cs" />
+ <Compile Include="IUsable.cs" />
+ <Compile Include="IVirtualJoystick.cs" />
+ <Compile Include="JoinGameButton.cs" />
+ <Compile Include="KerningPair.cs" />
+ <Compile Include="KeyboardJoystick.cs" />
+ <Compile Include="KeypadGame.cs" />
+ <Compile Include="KillAnimation.cs" />
+ <Compile Include="KillAnimType.cs" />
+ <Compile Include="KillButtonManager.cs" />
+ <Compile Include="KillOverlay.cs" />
+ <Compile Include="LanguageButton.cs" />
+ <Compile Include="LanguageSetter.cs" />
+ <Compile Include="LanguageUnit.cs" />
+ <Compile Include="LeafBehaviour.cs" />
+ <Compile Include="LeafMinigame.cs" />
+ <Compile Include="LetterTree.cs" />
+ <Compile Include="LifeSuppSystemType.cs" />
+ <Compile Include="LightSource.cs" />
+ <Compile Include="LobbyBehaviour.cs" />
+ <Compile Include="MainMenuManager.cs" />
+ <Compile Include="ManualDoor.cs" />
+ <Compile Include="MapBehaviour.cs" />
+ <Compile Include="MapConsole.cs" />
+ <Compile Include="MapCountOverlay.cs" />
+ <Compile Include="MapRoom.cs" />
+ <Compile Include="MapTaskOverlay.cs" />
+ <Compile Include="MatchMaker.cs" />
+ <Compile Include="MatchMakerGameButton.cs" />
+ <Compile Include="MedScanMinigame.cs" />
+ <Compile Include="MedScanSystem.cs" />
+ <Compile Include="MeetingHud.cs" />
+ <Compile Include="MeetingRoomManager.cs" />
+ <Compile Include="MemSafeStringExtensions.cs" />
+ <Compile Include="MeshRendererExtensions.cs" />
+ <Compile Include="Minigame.cs" />
+ <Compile Include="MMOnlineManager.cs" />
+ <Compile Include="MonoPInvokeCallbackAttribute.cs" />
+ <Compile Include="NameTextBehaviour.cs" />
+ <Compile Include="NavigationMinigame.cs" />
+ <Compile Include="NoOxyTask.cs" />
+ <Compile Include="NormalPlayerTask.cs" />
+ <Compile Include="NoShadowBehaviour.cs" />
+ <Compile Include="NotificationPopper.cs" />
+ <Compile Include="NumberOption.cs" />
+ <Compile Include="ObjectPoolBehavior.cs" />
+ <Compile Include="OffsetAdjustment.cs" />
+ <Compile Include="OneWayShadows.cs" />
+ <Compile Include="OptionBehaviour.cs" />
+ <Compile Include="OptionsConsole.cs" />
+ <Compile Include="OptionsMenuBehaviour.cs" />
+ <Compile Include="OverlayKillAnimation.cs" />
+ <Compile Include="Palette.cs" />
+ <Compile Include="ParallaxController.cs" />
+ <Compile Include="ParticleInfo.cs" />
+ <Compile Include="PassiveButton.cs" />
+ <Compile Include="PassiveButtonManager.cs" />
+ <Compile Include="PetBehaviour.cs" />
+ <Compile Include="PetsTab.cs" />
+ <Compile Include="PhysicsHelpers.cs" />
+ <Compile Include="PingTracker.cs" />
+ <Compile Include="PlayerAnimator.cs" />
+ <Compile Include="PlayerControl.cs" />
+ <Compile Include="PlayerParticle.cs" />
+ <Compile Include="PlayerParticleInfo.cs" />
+ <Compile Include="PlayerParticles.cs" />
+ <Compile Include="PlayerPhysics.cs" />
+ <Compile Include="PlayerTab.cs" />
+ <Compile Include="PlayerTask.cs" />
+ <Compile Include="PlayerVoteArea.cs" />
+ <Compile Include="PoolableBehavior.cs" />
+ <Compile Include="PoolablePlayer.cs" />
+ <Compile Include="PooledMapIcon.cs" />
+ <Compile Include="PowerTools\SpriteAnim.cs" />
+ <Compile Include="PowerTools\SpriteAnimEventHandler.cs" />
+ <Compile Include="PowerTools\SpriteAnimNodes.cs" />
+ <Compile Include="PowerTools\SpriteAnimNodeSync.cs" />
+ <Compile Include="PowerTools\WaitForAnimationFinish.cs" />
+ <Compile Include="ProgressTracker.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="PurchaseButton.cs" />
+ <Compile Include="PurchaseStates.cs" />
+ <Compile Include="RadioWaveBehaviour.cs" />
+ <Compile Include="RandomFill.cs" />
+ <Compile Include="ReactorMinigame.cs" />
+ <Compile Include="ReactorRoomWire.cs" />
+ <Compile Include="ReactorShipRoom.cs" />
+ <Compile Include="ReactorSystemType.cs" />
+ <Compile Include="ReactorTask.cs" />
+ <Compile Include="RefuelMinigame.cs" />
+ <Compile Include="RefuelStage.cs" />
+ <Compile Include="ReportButtonManager.cs" />
+ <Compile Include="ResolutionManager.cs" />
+ <Compile Include="ResolutionSlider.cs" />
+ <Compile Include="ResSetter.cs" />
+ <Compile Include="RingBuffer.cs" />
+ <Compile Include="RoomTracker.cs" />
+ <Compile Include="SabotageSystemType.cs" />
+ <Compile Include="SabotageTask.cs" />
+ <Compile Include="SampleMinigame.cs" />
+ <Compile Include="SaveManager.cs" />
+ <Compile Include="Scene0Controller.cs" />
+ <Compile Include="Scene1Controller.cs" />
+ <Compile Include="SceneChanger.cs" />
+ <Compile Include="SceneController.cs" />
+ <Compile Include="ScreenJoystick.cs" />
+ <Compile Include="Scroller.cs" />
+ <Compile Include="SecurityCameraSystemType.cs" />
+ <Compile Include="ServerInfo.cs" />
+ <Compile Include="ServerManager.cs" />
+ <Compile Include="ServerSelector.cs" />
+ <Compile Include="ServerSelectUi.cs" />
+ <Compile Include="SettingsMode.cs" />
+ <Compile Include="ShadowCamera.cs" />
+ <Compile Include="ShhhBehaviour.cs" />
+ <Compile Include="ShieldMinigame.cs" />
+ <Compile Include="ShipRoom.cs" />
+ <Compile Include="ShipStatus.cs" />
+ <Compile Include="ShowAdsState.cs" />
+ <Compile Include="SimonSaysGame.cs" />
+ <Compile Include="SinglePopHelp.cs" />
+ <Compile Include="SkinData.cs" />
+ <Compile Include="SkinLayer.cs" />
+ <Compile Include="SkinsTab.cs" />
+ <Compile Include="SlideBar.cs" />
+ <Compile Include="SortGameObject.cs" />
+ <Compile Include="SortMinigame.cs" />
+ <Compile Include="SoundGroup.cs" />
+ <Compile Include="SoundManager.cs" />
+ <Compile Include="SoundStarter.cs" />
+ <Compile Include="SpinAnimator.cs" />
+ <Compile Include="SpriteParticle.cs" />
+ <Compile Include="StarGen.cs" />
+ <Compile Include="StatsManager.cs" />
+ <Compile Include="StatsPopup.cs" />
+ <Compile Include="SteamBehaviour.cs" />
+ <Compile Include="SteamManager.cs" />
+ <Compile Include="SteamPurchasingModule.cs" />
+ <Compile Include="StoreMenu.cs" />
+ <Compile Include="StringExtensions.cs" />
+ <Compile Include="StringNames.cs" />
+ <Compile Include="StringOption.cs" />
+ <Compile Include="SubString.cs" />
+ <Compile Include="SubStringReader.cs" />
+ <Compile Include="SurvCamera.cs" />
+ <Compile Include="SurveillanceMinigame.cs" />
+ <Compile Include="SweepMinigame.cs" />
+ <Compile Include="SwitchMinigame.cs" />
+ <Compile Include="SwitchSystem.cs" />
+ <Compile Include="SystemConsole.cs" />
+ <Compile Include="SystemTypeHelpers.cs" />
+ <Compile Include="SystemTypes.cs" />
+ <Compile Include="TabButton.cs" />
+ <Compile Include="TabGroup.cs" />
+ <Compile Include="TaskAddButton.cs" />
+ <Compile Include="TaskAdderGame.cs" />
+ <Compile Include="TaskFolder.cs" />
+ <Compile Include="TaskPanelBehaviour.cs" />
+ <Compile Include="TaskSet.cs" />
+ <Compile Include="TaskTypes.cs" />
+ <Compile Include="TaskTypesHelpers.cs" />
+ <Compile Include="TempData.cs" />
+ <Compile Include="TextBox.cs" />
+ <Compile Include="TextController.cs" />
+ <Compile Include="TextLink.cs" />
+ <Compile Include="TextRenderer.cs" />
+ <Compile Include="TextTranslator.cs" />
+ <Compile Include="ToggleButtonBehaviour.cs" />
+ <Compile Include="ToggleOption.cs" />
+ <Compile Include="TowerBehaviour.cs" />
+ <Compile Include="TransitionOpen.cs" />
+ <Compile Include="TransitionType.cs" />
+ <Compile Include="TranslatedImageSet.cs" />
+ <Compile Include="TranslationController.cs" />
+ <Compile Include="TumbleBoxBehaviour.cs" />
+ <Compile Include="TuneRadioMinigame.cs" />
+ <Compile Include="TutorialManager.cs" />
+ <Compile Include="TutorialStatsManager.cs" />
+ <Compile Include="TwitterLink.cs" />
+ <Compile Include="UnlockManifoldsMinigame.cs" />
+ <Compile Include="UnlockPopUp.cs" />
+ <Compile Include="UploadDataGame.cs" />
+ <Compile Include="UploadDataTask.cs" />
+ <Compile Include="UseButtonManager.cs" />
+ <Compile Include="Vector2Range.cs" />
+ <Compile Include="VendingMinigame.cs" />
+ <Compile Include="VendingSlot.cs" />
+ <Compile Include="Vent.cs" />
+ <Compile Include="VersionShower.cs" />
+ <Compile Include="VerticalGauge.cs" />
+ <Compile Include="VirtualJoystick.cs" />
+ <Compile Include="VoteBanSystem.cs" />
+ <Compile Include="WaitForHostPopup.cs" />
+ <Compile Include="WaitForLerp.cs" />
+ <Compile Include="WeaponsMinigame.cs" />
+ <Compile Include="WeatherMinigame.cs" />
+ <Compile Include="WinningPlayerData.cs" />
+ <Compile Include="Wire.cs" />
+ <Compile Include="WireMinigame.cs" />
+ <Compile Include="WireNode.cs" />
+ <Compile Include="XXHash.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+</Project> \ No newline at end of file
diff --git a/Client/Assembly-CSharp/Assets/CoreScripts/Telemetry.cs b/Client/Assembly-CSharp/Assets/CoreScripts/Telemetry.cs
new file mode 100644
index 0000000..6d81ae0
--- /dev/null
+++ b/Client/Assembly-CSharp/Assets/CoreScripts/Telemetry.cs
@@ -0,0 +1,300 @@
+using System;
+using System.Collections.Generic;
+using InnerNet;
+using UnityEngine;
+using UnityEngine.Analytics;
+
+namespace Assets.CoreScripts
+{
+ public class Telemetry : DestroyableSingleton<Telemetry>
+ {
+ private static readonly string[] ColorNames = new string[]
+ {
+ "Red",
+ "Blue",
+ "Green",
+ "Pink",
+ "Orange",
+ "Yellow",
+ "Black",
+ "White",
+ "Purple",
+ "Brown"
+ };
+
+ private bool amHost;
+
+ private bool gameStarted;
+
+ private DateTime timeStarted;
+
+ public bool IsInitialized;
+
+ public Guid CurrentGuid;
+
+ public void Initialize()
+ {
+ this.Initialize(Guid.NewGuid());
+ }
+
+ public void Initialize(Guid gameGuid)
+ {
+ this.IsInitialized = true;
+ this.CurrentGuid = gameGuid;
+ }
+
+ public void StartGame(bool sendName, bool isHost, int playerCount, int impostorCount, GameModes gameMode, uint timesImpostor, uint gamesPlayed, uint crewStreak)
+ {
+ if (!SaveManager.SendTelemetry)
+ {
+ return;
+ }
+ this.gameStarted = true;
+ this.amHost = isHost;
+ this.timeStarted = DateTime.UtcNow;
+ Dictionary<string, object> dictionary = new Dictionary<string, object>
+ {
+ {
+ "Platform",
+ (byte)Application.platform
+ },
+ {
+ "TimesImpostor",
+ timesImpostor
+ },
+ {
+ "CrewStreak",
+ crewStreak
+ },
+ {
+ "GamesPlayed",
+ gamesPlayed
+ },
+ {
+ "GameMode",
+ gameMode
+ }
+ };
+ if (this.amHost)
+ {
+ dictionary.Add("PlayerCount", playerCount);
+ dictionary.Add("InfectedCount", impostorCount);
+ }
+ Analytics.CustomEvent("StartGame", dictionary);
+ }
+
+ public void WriteMeetingStarted(bool isEmergency)
+ {
+ if (!SaveManager.SendTelemetry)
+ {
+ return;
+ }
+ if (!this.amHost)
+ {
+ return;
+ }
+ Analytics.CustomEvent("MeetingStarted", new Dictionary<string, object>
+ {
+ {
+ "IsEmergency",
+ isEmergency
+ }
+ });
+ }
+
+ public void WriteMeetingEnded(byte[] results, float duration)
+ {
+ if (!SaveManager.SendTelemetry)
+ {
+ return;
+ }
+ if (!this.amHost)
+ {
+ return;
+ }
+ Analytics.CustomEvent("MeetingEnded", new Dictionary<string, object>
+ {
+ {
+ "IsEmergency",
+ duration
+ }
+ });
+ }
+
+ public void WritePosition(byte playerNum, Vector2 worldPos)
+ {
+ }
+
+ public void WriteMurder(byte sourcePlayerNum, byte targetPlayerNum, Vector3 worldPos)
+ {
+ if (!SaveManager.SendTelemetry)
+ {
+ return;
+ }
+ if (!this.gameStarted)
+ {
+ return;
+ }
+ Analytics.CustomEvent("Murder");
+ }
+
+ public void WriteSabotageUsed(SystemTypes systemType)
+ {
+ if (!SaveManager.SendTelemetry)
+ {
+ return;
+ }
+ if (!this.gameStarted)
+ {
+ return;
+ }
+ Analytics.CustomEvent("SabotageUsed", new Dictionary<string, object>
+ {
+ {
+ "SystemType",
+ systemType
+ }
+ });
+ }
+
+ public void WriteUse(byte playerNum, TaskTypes taskType, Vector3 worldPos)
+ {
+ if (!SaveManager.SendTelemetry)
+ {
+ return;
+ }
+ if (!this.gameStarted)
+ {
+ return;
+ }
+ Analytics.CustomEvent("ConsoleUsed", new Dictionary<string, object>
+ {
+ {
+ "TaskType",
+ taskType
+ }
+ });
+ }
+
+ public void WriteCompleteTask(byte playerNum, TaskTypes taskType)
+ {
+ if (!SaveManager.SendTelemetry)
+ {
+ return;
+ }
+ if (!this.gameStarted)
+ {
+ return;
+ }
+ Analytics.CustomEvent("TaskComplete", new Dictionary<string, object>
+ {
+ {
+ "TaskType",
+ taskType
+ }
+ });
+ }
+
+ internal void WriteDisconnect(DisconnectReasons reason)
+ {
+ if (!SaveManager.SendTelemetry)
+ {
+ return;
+ }
+ if (!this.gameStarted)
+ {
+ return;
+ }
+ Analytics.CustomEvent("Disconnect", new Dictionary<string, object>
+ {
+ {
+ "Reason",
+ reason
+ }
+ });
+ }
+
+ public void EndGame(GameOverReason endReason)
+ {
+ if (!SaveManager.SendTelemetry)
+ {
+ return;
+ }
+ if (!this.gameStarted)
+ {
+ return;
+ }
+ Dictionary<string, object> dictionary = new Dictionary<string, object>
+ {
+ {
+ "Reason",
+ endReason
+ }
+ };
+ if (this.amHost)
+ {
+ dictionary.Add("DurationSec", (DateTime.UtcNow - this.timeStarted).TotalSeconds);
+ }
+ Analytics.CustomEvent("EndGame", dictionary);
+ }
+
+ public void SendWho()
+ {
+ if (!SaveManager.SendTelemetry)
+ {
+ return;
+ }
+ if (!this.gameStarted)
+ {
+ return;
+ }
+ Analytics.CustomEvent("SentWho");
+ }
+
+ public void SelectInfected(int colorId, uint hatId)
+ {
+ if (!SaveManager.SendTelemetry)
+ {
+ return;
+ }
+ if (!this.gameStarted)
+ {
+ return;
+ }
+ Analytics.CustomEvent("SelectInfected", new Dictionary<string, object>
+ {
+ {
+ "Color",
+ Telemetry.ColorNames[colorId]
+ },
+ {
+ "Hat",
+ DestroyableSingleton<HatManager>.Instance.GetHatById(hatId).name
+ }
+ });
+ }
+
+ public void WonGame(int colorId, uint hatId)
+ {
+ if (!SaveManager.SendTelemetry)
+ {
+ return;
+ }
+ if (!this.gameStarted)
+ {
+ return;
+ }
+ Analytics.CustomEvent("WonGame", new Dictionary<string, object>
+ {
+ {
+ "Color",
+ Telemetry.ColorNames[colorId]
+ },
+ {
+ "Hat",
+ DestroyableSingleton<HatManager>.Instance.GetHatById(hatId).name
+ }
+ });
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/Asteroid.cs b/Client/Assembly-CSharp/Asteroid.cs
new file mode 100644
index 0000000..a633bef
--- /dev/null
+++ b/Client/Assembly-CSharp/Asteroid.cs
@@ -0,0 +1,71 @@
+using System;
+using System.Collections;
+using UnityEngine;
+
+public class Asteroid : PoolableBehavior
+{
+ public Vector3 TargetPosition { get; internal set; }
+
+ public Sprite[] AsteroidImages;
+
+ public Sprite[] BrokenImages;
+
+ private int imgIdx;
+
+ public FloatRange MoveSpeed = new FloatRange(2f, 5f);
+
+ public FloatRange RotateSpeed = new FloatRange(-10f, 10f);
+
+ public SpriteRenderer Explosion;
+
+ public void FixedUpdate()
+ {
+ base.transform.localRotation = Quaternion.Euler(0f, 0f, base.transform.localRotation.eulerAngles.z + this.RotateSpeed.Last * Time.fixedDeltaTime);
+ Vector3 a = this.TargetPosition - base.transform.localPosition;
+ if (a.sqrMagnitude > 0.05f)
+ {
+ a.Normalize();
+ base.transform.localPosition += a * this.MoveSpeed.Last * Time.fixedDeltaTime;
+ return;
+ }
+ this.OwnerPool.Reclaim(this);
+ }
+
+ public override void Reset()
+ {
+ base.enabled = true;
+ this.Explosion.enabled = false;
+ SpriteRenderer component = base.GetComponent<SpriteRenderer>();
+ this.imgIdx = this.AsteroidImages.RandomIdx<Sprite>();
+ component.sprite = this.AsteroidImages[this.imgIdx];
+ component.enabled = true;
+ ButtonBehavior component2 = base.GetComponent<ButtonBehavior>();
+ component2.enabled = true;
+ component2.OnClick.RemoveAllListeners();
+ base.transform.Rotate(0f, 0f, this.RotateSpeed.Next());
+ this.MoveSpeed.Next();
+ base.Reset();
+ }
+
+ public IEnumerator CoBreakApart()
+ {
+ base.enabled = false;
+ base.GetComponent<ButtonBehavior>().enabled = false;
+ this.Explosion.enabled = true;
+ yield return new WaitForLerp(0.1f, delegate(float t)
+ {
+ this.Explosion.transform.localScale = new Vector3(t, t, t);
+ });
+ yield return new WaitForSeconds(0.05f);
+ yield return new WaitForLerp(0.05f, delegate(float t)
+ {
+ this.Explosion.transform.localScale = new Vector3(1f - t, 1f - t, 1f - t);
+ });
+ SpriteRenderer rend = base.GetComponent<SpriteRenderer>();
+ yield return null;
+ rend.sprite = this.BrokenImages[this.imgIdx];
+ yield return new WaitForSeconds(0.2f);
+ this.OwnerPool.Reclaim(this);
+ yield break;
+ }
+}
diff --git a/Client/Assembly-CSharp/AutoOpenDoor.cs b/Client/Assembly-CSharp/AutoOpenDoor.cs
new file mode 100644
index 0000000..da09c70
--- /dev/null
+++ b/Client/Assembly-CSharp/AutoOpenDoor.cs
@@ -0,0 +1,37 @@
+using System;
+
+public class AutoOpenDoor : ManualDoor
+{
+ private const float ClosedDuration = 10f;
+
+ public SystemTypes Room;
+
+ public float ClosedTimer;
+
+ public float CooldownTimer;
+
+ public bool DoUpdate(float dt)
+ {
+ this.CooldownTimer = Math.Max(this.CooldownTimer - dt, 0f);
+ if (this.ClosedTimer > 0f)
+ {
+ this.ClosedTimer = Math.Max(this.ClosedTimer - dt, 0f);
+ if (this.ClosedTimer == 0f)
+ {
+ this.SetDoorway(true);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public override void SetDoorway(bool open)
+ {
+ if (!open)
+ {
+ this.ClosedTimer = 10f;
+ this.CooldownTimer = 30f;
+ }
+ base.SetDoorway(open);
+ }
+}
diff --git a/Client/Assembly-CSharp/BanButton.cs b/Client/Assembly-CSharp/BanButton.cs
new file mode 100644
index 0000000..0ed57a6
--- /dev/null
+++ b/Client/Assembly-CSharp/BanButton.cs
@@ -0,0 +1,52 @@
+using System;
+using System.Collections;
+using UnityEngine;
+
+public class BanButton : MonoBehaviour
+{
+ public BanMenu Parent { get; set; }
+
+ public TextRenderer NameText;
+
+ public SpriteRenderer Background;
+
+ public int TargetClientId;
+
+ public int numVotes;
+
+ public void Start()
+ {
+ this.Background.SetCooldownNormalizedUvs();
+ }
+
+ public void Select()
+ {
+ this.Background.color = new Color(1f, 1f, 1f, 1f);
+ this.Parent.Select(this.TargetClientId);
+ }
+
+ public void Unselect()
+ {
+ this.Background.color = new Color(0.3f, 0.3f, 0.3f, 0.5f);
+ }
+
+ public void SetVotes(int newVotes)
+ {
+ base.StopAllCoroutines();
+ base.StartCoroutine(this.CoSetVotes(this.numVotes, newVotes));
+ this.numVotes = newVotes;
+ }
+
+ private IEnumerator CoSetVotes(int oldNum, int newNum)
+ {
+ float num = (float)oldNum / 3f;
+ float end = (float)newNum / 3f;
+ for (float timer = 0f; timer < 0.2f; timer += Time.deltaTime)
+ {
+ this.Background.material.SetFloat("_Percent", Mathf.SmoothStep(end, end, timer / 0.2f));
+ yield return null;
+ }
+ this.Background.material.SetFloat("_Percent", end);
+ yield break;
+ }
+}
diff --git a/Client/Assembly-CSharp/BanMenu.cs b/Client/Assembly-CSharp/BanMenu.cs
new file mode 100644
index 0000000..eaa7440
--- /dev/null
+++ b/Client/Assembly-CSharp/BanMenu.cs
@@ -0,0 +1,153 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using InnerNet;
+using UnityEngine;
+
+public class BanMenu : MonoBehaviour
+{
+ public BanButton BanButtonPrefab;
+
+ public SpriteRenderer Background;
+
+ public SpriteRenderer BanButton;
+
+ public SpriteRenderer KickButton;
+
+ public GameObject ContentParent;
+
+ public int selected = -1;
+
+ [HideInInspector]
+ public List<BanButton> allButtons = new List<BanButton>();
+
+ public void SetVisible(bool show)
+ {
+ show &= (PlayerControl.LocalPlayer && PlayerControl.LocalPlayer.Data != null && !PlayerControl.LocalPlayer.Data.IsDead);
+ show &= AmongUsClient.Instance.CanKick();
+ show &= (MeetingHud.Instance || !ShipStatus.Instance);
+ this.BanButton.gameObject.SetActive(AmongUsClient.Instance.CanBan());
+ this.KickButton.gameObject.SetActive(AmongUsClient.Instance.CanKick());
+ base.GetComponent<SpriteRenderer>().enabled = show;
+ base.GetComponent<PassiveButton>().enabled = show;
+ }
+
+ private void Update()
+ {
+ for (int i = 0; i < AmongUsClient.Instance.allClients.Count; i++)
+ {
+ try
+ {
+ ClientData client = AmongUsClient.Instance.allClients[i];
+ if (client == null)
+ {
+ break;
+ }
+ int[] source;
+ if (VoteBanSystem.Instance.HasMyVote(client.Id) && VoteBanSystem.Instance.Votes.TryGetValue(client.Id, out source))
+ {
+ int num = source.Count((int c) => c != 0);
+ BanButton banButton = this.allButtons.FirstOrDefault((BanButton b) => b.TargetClientId == client.Id);
+ if (banButton && banButton.numVotes != num)
+ {
+ banButton.SetVotes(num);
+ }
+ }
+ }
+ catch
+ {
+ break;
+ }
+ }
+ }
+
+ public void Show()
+ {
+ if (this.ContentParent.activeSelf)
+ {
+ this.Hide();
+ return;
+ }
+ this.selected = -1;
+ this.KickButton.color = Color.gray;
+ this.BanButton.color = Color.gray;
+ this.ContentParent.SetActive(true);
+ int num = 0;
+ if (AmongUsClient.Instance)
+ {
+ List<ClientData> allClients = AmongUsClient.Instance.allClients;
+ for (int i = 0; i < allClients.Count; i++)
+ {
+ ClientData clientData = allClients[i];
+ if (clientData.Id != AmongUsClient.Instance.ClientId && clientData.Character)
+ {
+ GameData.PlayerInfo data = clientData.Character.Data;
+ if (!string.IsNullOrWhiteSpace(data.PlayerName))
+ {
+ BanButton banButton = UnityEngine.Object.Instantiate<BanButton>(this.BanButtonPrefab, this.ContentParent.transform);
+ banButton.transform.localPosition = new Vector3(-0.2f, -0.15f - 0.4f * (float)num, -1f);
+ banButton.Parent = this;
+ banButton.NameText.Text = data.PlayerName;
+ banButton.TargetClientId = clientData.Id;
+ banButton.Unselect();
+ this.allButtons.Add(banButton);
+ num++;
+ }
+ }
+ }
+ }
+ this.KickButton.transform.localPosition = new Vector3(-0.8f, -0.15f - 0.4f * (float)num - 0.1f, -1f);
+ this.BanButton.transform.localPosition = new Vector3(0.3f, -0.15f - 0.4f * (float)num - 0.1f, -1f);
+ float num2 = 0.3f + (float)(num + 1) * 0.4f;
+ this.Background.size = new Vector2(3f, num2);
+ this.Background.GetComponent<BoxCollider2D>().size = new Vector2(3f, num2);
+ this.Background.transform.localPosition = new Vector3(0f, -num2 / 2f + 0.15f, 0.1f);
+ }
+
+ public void Hide()
+ {
+ this.selected = -1;
+ this.ContentParent.SetActive(false);
+ for (int i = 0; i < this.allButtons.Count; i++)
+ {
+ UnityEngine.Object.Destroy(this.allButtons[i].gameObject);
+ }
+ this.allButtons.Clear();
+ }
+
+ public void Select(int client)
+ {
+ if (VoteBanSystem.Instance.HasMyVote(client))
+ {
+ return;
+ }
+ this.selected = client;
+ for (int i = 0; i < this.allButtons.Count; i++)
+ {
+ BanButton banButton = this.allButtons[i];
+ if (banButton.TargetClientId != client)
+ {
+ banButton.Unselect();
+ }
+ }
+ this.KickButton.color = Color.white;
+ this.BanButton.color = Color.white;
+ }
+
+ public void Kick(bool ban)
+ {
+ if (this.selected >= 0)
+ {
+ if (AmongUsClient.Instance.CanBan())
+ {
+ AmongUsClient.Instance.KickPlayer(this.selected, ban);
+ this.Hide();
+ }
+ else
+ {
+ VoteBanSystem.Instance.CmdAddVote(this.selected);
+ }
+ }
+ this.Select(-1);
+ }
+}
diff --git a/Client/Assembly-CSharp/BlockedWords.cs b/Client/Assembly-CSharp/BlockedWords.cs
new file mode 100644
index 0000000..af08a2f
--- /dev/null
+++ b/Client/Assembly-CSharp/BlockedWords.cs
@@ -0,0 +1,877 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+public static class BlockedWords
+{
+ public static readonly HashSet<char> SymbolChars = new HashSet<char>
+ {
+ '?',
+ '!',
+ ',',
+ '.',
+ '\'',
+ ':',
+ ';',
+ '(',
+ ')',
+ '/',
+ '\\',
+ '%',
+ '^',
+ '&',
+ '-',
+ '='
+ };
+
+ private static readonly LetterTree SkipList;
+
+ public static readonly string[] AllWords = new string[]
+ {
+ "anal~",
+ "analingus",
+ "anilingus",
+ "anus^",
+ "apeshit",
+ "areola",
+ "areole",
+ "arian~",
+ "arse~",
+ "arsehole",
+ "aryan~",
+ "ass^",
+ "assbandit",
+ "assbang",
+ "assbite",
+ "assclown",
+ "asscock",
+ "asscracker",
+ "asses~",
+ "assface",
+ "assfuck",
+ "assfukka",
+ "assgoblin",
+ "asshat",
+ "asshead",
+ "assho1e",
+ "asshole",
+ "asshopper",
+ "assjabber",
+ "assjacker",
+ "asslick",
+ "assmaster",
+ "assmonkey",
+ "assmucus",
+ "assmunch",
+ "assnigger",
+ "asspirate",
+ "asswad",
+ "asswhole",
+ "asswipe",
+ "autoerotic",
+ "axwound",
+ "azazel",
+ "azz",
+ "babybatter",
+ "babyjuice",
+ "ballbag",
+ "ballgag",
+ "ballgravy",
+ "ballkicking",
+ "balllicking",
+ "balls~",
+ "ballsac",
+ "ballsak",
+ "bampot",
+ "bangbros",
+ "bareback",
+ "barelylegal",
+ "barenaked",
+ "bastard",
+ "bastinado",
+ "battyboy",
+ "bawdy",
+ "bbw",
+ "bdsm",
+ "beaner",
+ "beardedclam",
+ "beastial",
+ "beatch",
+ "beaver",
+ "beefcurtain",
+ "beeyotch",
+ "bellend",
+ "beotch",
+ "bescumber",
+ "bestial",
+ "b!atch",
+ "b!gblack",
+ "b!gbreasts",
+ "b!gknockers",
+ "b!gtits",
+ "b!mbo",
+ "b!nt",
+ "b!rdlock",
+ "b!tch",
+ "bisexual",
+ "blackcock",
+ "blondeaction",
+ "bloodclaat",
+ "bloodyhell",
+ "blowjob",
+ "blowme",
+ "blowmud",
+ "blowyourload",
+ "bluewaffle",
+ "blumpkin",
+ "b0iolas",
+ "b0llock",
+ "b0llok",
+ "b0llox",
+ "b0ndage",
+ "b0ned",
+ "b0ner",
+ "b0ng",
+ "b00b",
+ "b00ger",
+ "b00kie",
+ "b00tee",
+ "b00tie",
+ "b00ty",
+ "b00ze",
+ "b00zy",
+ "b0som",
+ "breasts",
+ "breeder",
+ "brotherfucker",
+ "brownshowers",
+ "brunetteaction",
+ "buceta",
+ "bukkake",
+ "bulldyke",
+ "bulletvibe",
+ "bullshit",
+ "bullturds",
+ "buncombe",
+ "bung",
+ "bunnyfucker",
+ "bustaload",
+ "busty",
+ "buttcheeks",
+ "buttfuck",
+ "butthole",
+ "buttmuch",
+ "buttmunch",
+ "buttpirate",
+ "buttplug",
+ "caca",
+ "cahone",
+ "cameltoe",
+ "camgirl",
+ "camslut",
+ "camwhore",
+ "carpetmuncher",
+ "cawk",
+ "cervix",
+ "chesticle",
+ "chichiman",
+ "chickwithadick",
+ "childfucker",
+ "chinc",
+ "chink",
+ "choad",
+ "chocice",
+ "chocolaterosebuds",
+ "chode",
+ "chotabags",
+ "cipa~",
+ "circlejerk",
+ "clevelandsteamer",
+ "cl1max",
+ "cl1t",
+ "cloverclamps",
+ "clunge",
+ "clusterfuck",
+ "cnut",
+ "c0cain",
+ "c0ccydynia",
+ "c0ck",
+ "c0ffindodger",
+ "c0ital",
+ "c0k",
+ "c0mmie",
+ "c0ndom",
+ "c0ochie",
+ "c0ochy",
+ "c0on",
+ "c0oter",
+ "c0prolagnia",
+ "c0prophilia",
+ "c0psomewood",
+ "c0rksucker",
+ "c0rnhole",
+ "c0rpulent",
+ "c0rpwhore",
+ "c0x",
+ "crack",
+ "creampie",
+ "cretin",
+ "crikey",
+ "cripple",
+ "crotte",
+ "cum~",
+ "cumbubble",
+ "cumchugger",
+ "cumdump",
+ "cumfreak",
+ "cumguzzler",
+ "cumjockey",
+ "cums~",
+ "cumtart",
+ "cunilingus",
+ "cunnie",
+ "cunny",
+ "cunt",
+ "cutrope",
+ "cyalis",
+ "cyberfuc",
+ "dago",
+ "darkie",
+ "daterape",
+ "dawgiestyle",
+ "deepthroat",
+ "deggo",
+ "dendrophilia",
+ "dick",
+ "diddle",
+ "dike",
+ "dild0",
+ "diligaf",
+ "dillweed",
+ "dimwit",
+ "dingle",
+ "dink",
+ "dipship",
+ "dipshit",
+ "dirsa",
+ "dirtypillows",
+ "dirtysanchez",
+ "dlck",
+ "d0gfucker",
+ "d0ggiestyle",
+ "d0ggin",
+ "d0ggystyle",
+ "d0gstyle",
+ "d0lcett",
+ "d0mination",
+ "d0minatrix",
+ "d0mmes",
+ "d0ng",
+ "d0nkeypunch",
+ "d0nkeyribber",
+ "d0ochbag",
+ "d0ofus",
+ "d0okie",
+ "d0osh",
+ "d0pey",
+ "d0ubledong",
+ "d0ublelift",
+ "d0ublepenetration",
+ "d0uch3",
+ "dpaction",
+ "drilldo",
+ "dryhump",
+ "duche",
+ "dumass",
+ "dumbass",
+ "dumbcunt",
+ "dumbfuck",
+ "dumbshit",
+ "dummy",
+ "dumshit",
+ "dvda",
+ "dyke",
+ "eatadick",
+ "eathairpie",
+ "eatmyass",
+ "ecchi",
+ "ejaculate",
+ "ejaculating",
+ "ejaculation",
+ "ejakulate",
+ "erect",
+ "erotic",
+ "erotism",
+ "essohbee",
+ "eunuch",
+ "extacy",
+ "extasy",
+ "f4cial",
+ "f4ck",
+ "f4g",
+ "f4ig",
+ "f4nny",
+ "f4nyy",
+ "f4tass",
+ "fcuk",
+ "fecal",
+ "feck",
+ "feist",
+ "felch",
+ "fellate",
+ "fellatio",
+ "feltch",
+ "femalesquirting",
+ "femdom",
+ "fenian",
+ "figging",
+ "fingerbang",
+ "fingerfuck",
+ "fingering",
+ "fisted",
+ "fistfuck",
+ "fisting",
+ "fisty",
+ "flange",
+ "flaps",
+ "fleshflute",
+ "flogthelog",
+ "floozy",
+ "foad",
+ "foah",
+ "fondle",
+ "foobar",
+ "fook",
+ "footfetish",
+ "footjob",
+ "foreskin",
+ "freex",
+ "frenchify",
+ "frigg",
+ "frotting",
+ "fubar",
+ "fuc",
+ "fudgepacker",
+ "fuk",
+ "fuq",
+ "furfag",
+ "furryfag",
+ "futanari",
+ "fuck",
+ "fux",
+ "fvck",
+ "fxck",
+ "gangbang",
+ "ganja",
+ "gash",
+ "gassyass",
+ "gay",
+ "genderbender",
+ "genitals",
+ "gey~",
+ "gfy",
+ "ghay",
+ "ghey",
+ "giantcock",
+ "gigolo",
+ "gippo",
+ "girlon",
+ "girlsgonewild",
+ "glans",
+ "goatcx",
+ "goatse",
+ "gokkun",
+ "goldenshower",
+ "golliwog",
+ "gonad",
+ "gooch",
+ "googirl",
+ "gook",
+ "goregasm",
+ "gringo",
+ "grope",
+ "groupsex",
+ "gspot",
+ "guido",
+ "guro",
+ "hamflap",
+ "handjob",
+ "hardon",
+ "hell~",
+ "hells",
+ "hemp",
+ "homo^",
+ "hentai",
+ "heroin",
+ "heshe~",
+ "hircismus",
+ "hitler",
+ "hugefat",
+ "hump~",
+ "hussy",
+ "hymen",
+ "inbred",
+ "incest",
+ "injun",
+ "intercourse",
+ "jackass",
+ "jackhole",
+ "jackoff",
+ "jaggi",
+ "jagoff",
+ "jailbait",
+ "jellydonut",
+ "jigaboo",
+ "jiggerboo",
+ "jism",
+ "jiz",
+ "jock",
+ "juggs",
+ "junglebunny",
+ "junkie",
+ "junky",
+ "kafir",
+ "kawk",
+ "kike",
+ "kinbaku",
+ "kinkster",
+ "kinky",
+ "klan",
+ "kock",
+ "kondum",
+ "kooch",
+ "kootch",
+ "kraut",
+ "kum",
+ "kunilingus",
+ "kunja",
+ "kunt~",
+ "kwif",
+ "kyke",
+ "labia",
+ "lameass",
+ "lardass",
+ "l3i+ch",
+ "l3monparty",
+ "l3per",
+ "l3sbian",
+ "l3sbo~",
+ "l3z~",
+ "lolita",
+ "looney",
+ "lovemaking",
+ "lube",
+ "lust",
+ "m4fugly",
+ "m4kemecome",
+ "m4lesquirting",
+ "m4ms",
+ "m45ochist",
+ "m45sa",
+ "m45terbate",
+ "m45terbating",
+ "m45terbation",
+ "m45terb8",
+ "m45turbate",
+ "m45turbating",
+ "m45turbation",
+ "mcfagget",
+ "menageatrois",
+ "menses",
+ "menstruate",
+ "menstruation",
+ "meth~",
+ "mfucking",
+ "mick",
+ "microphallus",
+ "middlefinger",
+ "midget",
+ "milf",
+ "minge",
+ "missionaryposition",
+ "m0f0",
+ "m0lest",
+ "m0olie",
+ "m0omoofoofoo",
+ "m0ron",
+ "m0thafuck",
+ "m0therfuck",
+ "m0undofvenus",
+ "mrhands",
+ "muff",
+ "munging",
+ "munter",
+ "mutha",
+ "muther",
+ "naked",
+ "nambla",
+ "napalm",
+ "nappy",
+ "nawashi",
+ "nazi",
+ "ngga^",
+ "nggr",
+ "nlgger",
+ "nlgga",
+ "nlggr",
+ "n1gaboo",
+ "n1qqa",
+ "n1qqer",
+ "n1gga",
+ "n1bba",
+ "n1ggr",
+ "n1gger",
+ "n1ggle",
+ "n1glet",
+ "n1gnog",
+ "n1mphomania",
+ "n1mrod",
+ "n1nny",
+ "n1pple",
+ "nonce",
+ "nsfwimages",
+ "nude",
+ "nudity",
+ "numbnuts",
+ "nutbutter",
+ "nutsack",
+ "nutter",
+ "nympho",
+ "octopussy",
+ "oldbag",
+ "omorashi",
+ "onecuptwogirls",
+ "oneguyonejar",
+ "opiate",
+ "opium",
+ "orally",
+ "orgasim",
+ "orgasm",
+ "orgies",
+ "orgy",
+ "ovary",
+ "ovum",
+ "paedophile",
+ "paki~",
+ "panooch",
+ "pansy",
+ "pantie",
+ "panty",
+ "pecker",
+ "pedo~",
+ "pedophile",
+ "pegging",
+ "penetrate",
+ "penetration",
+ "penial",
+ "penile",
+ "penis",
+ "perversion",
+ "phallic",
+ "phonesex",
+ "phuck",
+ "phuk",
+ "phuq",
+ "pigfucker",
+ "pikey",
+ "pillowbiter",
+ "pimp",
+ "pinko~",
+ "playboy",
+ "pleasurechest",
+ "p0lack",
+ "p0lesmoker",
+ "p0llock",
+ "p0nyplay",
+ "p0on",
+ "p0rchmonkey",
+ "p0rn",
+ "prick",
+ "prig",
+ "princealbertpiercing",
+ "pron",
+ "prostitute",
+ "prude",
+ "psycho",
+ "pthc",
+ "pube",
+ "pubic",
+ "pubis",
+ "punani",
+ "punkass",
+ "punky",
+ "punta",
+ "puss",
+ "puta~",
+ "puto~",
+ "queaf",
+ "queef",
+ "queer",
+ "quicky",
+ "quim",
+ "racy",
+ "raghead",
+ "ragingboner",
+ "rape~",
+ "raper~",
+ "raping",
+ "rapist",
+ "ratard",
+ "raunch",
+ "rectal",
+ "rectum",
+ "rectus",
+ "reefer",
+ "reich",
+ "renob",
+ "retard",
+ "reversecowgirl",
+ "revue",
+ "rimjaw",
+ "rimjob",
+ "rimming",
+ "ritard",
+ "rosypalm",
+ "rtard",
+ "rubbish",
+ "rump",
+ "ruski",
+ "rustytrombone",
+ "sadism",
+ "sadist",
+ "sambo",
+ "sandbar",
+ "sandler",
+ "sandnigger",
+ "sanger",
+ "santorum",
+ "sausagequeen",
+ "scag",
+ "scantily",
+ "scat",
+ "schizo",
+ "schlong",
+ "scissoring",
+ "scroat",
+ "scrog",
+ "scrot",
+ "scrud",
+ "seaman",
+ "seamen",
+ "seks",
+ "semen",
+ "sex",
+ "shag",
+ "shamedame",
+ "shavedbeaver",
+ "shavedpussy",
+ "shemale",
+ "shibari",
+ "shirtlifter",
+ "shit^",
+ "shiz",
+ "shota",
+ "shrimping",
+ "sissy",
+ "skag",
+ "skank",
+ "skeet",
+ "skullfuck",
+ "slag",
+ "slanteye",
+ "slave",
+ "sleaze",
+ "sleazy",
+ "slope",
+ "slut",
+ "smartass",
+ "smut",
+ "snatch",
+ "snowballing",
+ "snuff",
+ "s0doff",
+ "s0dom",
+ "s0nofabitch",
+ "s0nofawhore",
+ "spade",
+ "sperm",
+ "spic~",
+ "spick",
+ "spik~",
+ "splooge",
+ "spooge",
+ "spreadlegs",
+ "spunk",
+ "stfu",
+ "stiffy",
+ "strapon",
+ "strappado",
+ "styledoggy",
+ "suckass",
+ "suckingass",
+ "suicidegirls",
+ "sultrywomen",
+ "sumofabiatch",
+ "swastika",
+ "swinger",
+ "taintedlove",
+ "tampon",
+ "tard",
+ "tastemy",
+ "tawdry",
+ "teabagging",
+ "teat",
+ "teets",
+ "teez",
+ "teste~",
+ "testes",
+ "testical",
+ "testicle",
+ "testis",
+ "threesome",
+ "throating",
+ "thundercunt",
+ "thot~",
+ "t1edup",
+ "t1ghtwhite",
+ "t1nkle",
+ "t1t`",
+ "t1ts`",
+ "t1tty",
+ "t1ttie",
+ "tongueina",
+ "toots",
+ "topless",
+ "tosser",
+ "towelhead",
+ "tramp",
+ "tranny",
+ "transsexual",
+ "trashy",
+ "tribadism",
+ "tubgirl",
+ "turd",
+ "tush",
+ "tw4t^",
+ "twink",
+ "twofingers",
+ "twogirlsonecup",
+ "twunt",
+ "unclefucker",
+ "undies",
+ "undressing",
+ "upskirt",
+ "urethraplay",
+ "urinal",
+ "urine",
+ "urophilia",
+ "uterus",
+ "vajayjay",
+ "vajj",
+ "valium",
+ "venusmound",
+ "veqtable",
+ "v14gra",
+ "v1brator",
+ "v1gra",
+ "v1oletwand",
+ "v1rgin",
+ "v1xen",
+ "vjayjay",
+ "vodka",
+ "vomit",
+ "vorarephilia",
+ "voyeur",
+ "vulgar",
+ "vulva",
+ "wang",
+ "wank",
+ "wazoo",
+ "wedgie",
+ "weed",
+ "weenie",
+ "weewee",
+ "weiner",
+ "wetback",
+ "wetdream",
+ "whitepower",
+ "whiz",
+ "wh0ar~",
+ "wh0ars",
+ "wh0ralicious",
+ "wh0re^",
+ "wh0ring^",
+ "wigger",
+ "windowlicker",
+ "wiseass",
+ "w0g~",
+ "w00se",
+ "w0p~",
+ "wrappingmen",
+ "wrinkledstarfish",
+ "xrated",
+ "xxx",
+ "yaoi",
+ "yeasty",
+ "yellowshowers",
+ "yiffy",
+ "yobbo",
+ "zibbi",
+ "zoophilia",
+ "zubb"
+ };
+
+ private class LengthCompare : IComparer<string>
+ {
+ public static readonly BlockedWords.LengthCompare Instance = new BlockedWords.LengthCompare();
+
+ public int Compare(string x, string y)
+ {
+ return -x.Length.CompareTo(y.Length);
+ }
+ }
+
+ static BlockedWords()
+ {
+ BlockedWords.SkipList = new LetterTree();
+ for (int i = 0; i < BlockedWords.AllWords.Length; i++)
+ {
+ BlockedWords.SkipList.AddWord(BlockedWords.AllWords[i]);
+ }
+ }
+
+ public static bool ContainsWord(string chatText)
+ {
+ for (int i = 0; i < chatText.Length; i++)
+ {
+ if (BlockedWords.SkipList.Search(chatText, i) > 0)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static string CensorWords(string chatText)
+ {
+ StringBuilder stringBuilder = new StringBuilder(chatText);
+ for (int i = 0; i < chatText.Length; i++)
+ {
+ int num = BlockedWords.SkipList.Search(stringBuilder, i);
+ if (num > 0)
+ {
+ for (int j = 0; j < num; j++)
+ {
+ stringBuilder[i + j] = '*';
+ }
+ i = i + num - 1;
+ }
+ }
+ return stringBuilder.ToString();
+ }
+
+ private static bool IsLetter(char letter)
+ {
+ return letter != ' ' && letter != '\r' && letter != '\n' && !BlockedWords.SymbolChars.Contains(letter);
+ }
+}
diff --git a/Client/Assembly-CSharp/BoolRange.cs b/Client/Assembly-CSharp/BoolRange.cs
new file mode 100644
index 0000000..866c81b
--- /dev/null
+++ b/Client/Assembly-CSharp/BoolRange.cs
@@ -0,0 +1,10 @@
+using System;
+using UnityEngine;
+
+public class BoolRange
+{
+ public static bool Next(float p = 0.5f)
+ {
+ return UnityEngine.Random.value <= p;
+ }
+}
diff --git a/Client/Assembly-CSharp/ButtonBehavior.cs b/Client/Assembly-CSharp/ButtonBehavior.cs
new file mode 100644
index 0000000..aa941c8
--- /dev/null
+++ b/Client/Assembly-CSharp/ButtonBehavior.cs
@@ -0,0 +1,64 @@
+using System;
+using UnityEngine;
+using UnityEngine.UI;
+
+public class ButtonBehavior : MonoBehaviour
+{
+ public bool OnUp = true;
+
+ public bool OnDown;
+
+ public bool Repeat;
+
+ public Button.ButtonClickedEvent OnClick = new Button.ButtonClickedEvent();
+
+ private Controller myController = new Controller();
+
+ private Collider2D[] colliders;
+
+ private float downTime;
+
+ public void OnEnable()
+ {
+ this.colliders = base.GetComponents<Collider2D>();
+ this.myController.Reset();
+ }
+
+ public void Update()
+ {
+ this.myController.Update();
+ foreach (Collider2D coll in this.colliders)
+ {
+ switch (this.myController.CheckDrag(coll, false))
+ {
+ case DragState.TouchStart:
+ if (this.OnDown)
+ {
+ this.OnClick.Invoke();
+ }
+ break;
+ case DragState.Dragging:
+ if (this.Repeat)
+ {
+ this.downTime += Time.fixedDeltaTime;
+ if (this.downTime >= 0.3f)
+ {
+ this.downTime = 0f;
+ this.OnClick.Invoke();
+ }
+ }
+ else
+ {
+ this.downTime = 0f;
+ }
+ break;
+ case DragState.Released:
+ if (this.OnUp)
+ {
+ this.OnClick.Invoke();
+ }
+ break;
+ }
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/ButtonRolloverHandler.cs b/Client/Assembly-CSharp/ButtonRolloverHandler.cs
new file mode 100644
index 0000000..963058d
--- /dev/null
+++ b/Client/Assembly-CSharp/ButtonRolloverHandler.cs
@@ -0,0 +1,35 @@
+using System;
+using UnityEngine;
+using UnityEngine.Events;
+
+public class ButtonRolloverHandler : MonoBehaviour
+{
+ public SpriteRenderer Target;
+
+ public Color OverColor = Color.green;
+
+ public Color OutColor = Color.white;
+
+ public AudioClip HoverSound;
+
+ public void Start()
+ {
+ PassiveButton component = base.GetComponent<PassiveButton>();
+ component.OnMouseOver.AddListener(new UnityAction(this.DoMouseOver));
+ component.OnMouseOut.AddListener(new UnityAction(this.DoMouseOut));
+ }
+
+ public void DoMouseOver()
+ {
+ this.Target.color = this.OverColor;
+ if (this.HoverSound)
+ {
+ SoundManager.Instance.PlaySound(this.HoverSound, false, 1f);
+ }
+ }
+
+ public void DoMouseOut()
+ {
+ this.Target.color = this.OutColor;
+ }
+}
diff --git a/Client/Assembly-CSharp/CardSlideGame.cs b/Client/Assembly-CSharp/CardSlideGame.cs
new file mode 100644
index 0000000..3c423a5
--- /dev/null
+++ b/Client/Assembly-CSharp/CardSlideGame.cs
@@ -0,0 +1,190 @@
+using System;
+using System.Collections;
+using UnityEngine;
+
+public class CardSlideGame : Minigame
+{
+ private Color gray = new Color(0.45f, 0.45f, 0.45f);
+
+ private Color green = new Color(0f, 0.8f, 0f);
+
+ private CardSlideGame.TaskStages State;
+
+ private Controller myController = new Controller();
+
+ private FloatRange XRange = new FloatRange(-2.38f, 2.38f);
+
+ public FloatRange AcceptedTime = new FloatRange(0.4f, 0.6f);
+
+ public Collider2D col;
+
+ public SpriteRenderer redLight;
+
+ public SpriteRenderer greenLight;
+
+ public TextRenderer StatusText;
+
+ public AudioClip AcceptSound;
+
+ public AudioClip[] CardMove;
+
+ public AudioClip WalletOut;
+
+ public float dragTime;
+
+ private bool moving;
+
+ private enum TaskStages
+ {
+ Before,
+ Animating,
+ Inserted,
+ After
+ }
+
+ public void Update()
+ {
+ if (this.MyNormTask.IsComplete)
+ {
+ return;
+ }
+ this.myController.Update();
+ Vector3 localPosition = this.col.transform.localPosition;
+ switch (this.myController.CheckDrag(this.col, false))
+ {
+ case DragState.NoTouch:
+ if (this.State == CardSlideGame.TaskStages.Inserted)
+ {
+ localPosition.x = Mathf.Lerp(localPosition.x, this.XRange.min, Time.deltaTime * 4f);
+ }
+ break;
+ case DragState.TouchStart:
+ this.dragTime = 0f;
+ break;
+ case DragState.Dragging:
+ if (this.State == CardSlideGame.TaskStages.Inserted)
+ {
+ Vector2 vector = this.myController.DragPosition - base.transform.position;
+ vector.x = this.XRange.Clamp(vector.x);
+ if (vector.x - localPosition.x > 0.01f)
+ {
+ this.dragTime += Time.deltaTime;
+ this.redLight.color = this.gray;
+ this.greenLight.color = this.gray;
+ if (!this.moving)
+ {
+ this.moving = true;
+ if (Constants.ShouldPlaySfx())
+ {
+ SoundManager.Instance.PlaySound(this.CardMove.Random<AudioClip>(), false, 1f);
+ }
+ }
+ }
+ localPosition.x = vector.x;
+ }
+ break;
+ case DragState.Released:
+ this.moving = false;
+ if (this.State == CardSlideGame.TaskStages.Before)
+ {
+ this.State = CardSlideGame.TaskStages.Animating;
+ base.StartCoroutine(this.InsertCard());
+ }
+ else if (this.State == CardSlideGame.TaskStages.Inserted)
+ {
+ if (this.XRange.max - localPosition.x < 0.05f)
+ {
+ if (this.AcceptedTime.Contains(this.dragTime))
+ {
+ if (Constants.ShouldPlaySfx())
+ {
+ SoundManager.Instance.PlaySound(this.AcceptSound, false, 1f);
+ }
+ this.State = CardSlideGame.TaskStages.After;
+ this.StatusText.Text = "Accepted. Thank you.";
+ base.StartCoroutine(this.PutCardBack());
+ if (this.MyNormTask)
+ {
+ this.MyNormTask.NextStep();
+ }
+ this.redLight.color = this.gray;
+ this.greenLight.color = this.green;
+ }
+ else
+ {
+ if (this.AcceptedTime.max < this.dragTime)
+ {
+ this.StatusText.Text = "Too slow. Try again";
+ }
+ else
+ {
+ this.StatusText.Text = "Too fast. Try again.";
+ }
+ this.redLight.color = Color.red;
+ this.greenLight.color = this.gray;
+ }
+ }
+ else
+ {
+ this.StatusText.Text = "Bad read. Try again.";
+ this.redLight.color = Color.red;
+ this.greenLight.color = this.gray;
+ }
+ }
+ break;
+ }
+ this.col.transform.localPosition = localPosition;
+ }
+
+ private IEnumerator PutCardBack()
+ {
+ if (Constants.ShouldPlaySfx())
+ {
+ SoundManager.Instance.PlaySound(this.WalletOut, false, 1f);
+ }
+ Vector3 pos = this.col.transform.localPosition;
+ Vector3 targ = new Vector3(-1.11f, -1.9f, pos.z);
+ float time = 0f;
+ for (;;)
+ {
+ float t = Mathf.Min(1f, time / 0.6f);
+ this.col.transform.localPosition = Vector3.Lerp(pos, targ, t);
+ this.col.transform.localScale = Vector3.Lerp(Vector3.one, Vector3.one * 0.75f, t);
+ if (time > 0.6f)
+ {
+ break;
+ }
+ yield return null;
+ time += Time.deltaTime;
+ }
+ base.StartCoroutine(base.CoStartClose(0.75f));
+ yield break;
+ }
+
+ private IEnumerator InsertCard()
+ {
+ if (Constants.ShouldPlaySfx())
+ {
+ SoundManager.Instance.PlaySound(this.WalletOut, false, 1f);
+ }
+ Vector3 pos = this.col.transform.localPosition;
+ Vector3 targ = new Vector3(this.XRange.min, 0.75f, pos.z);
+ float time = 0f;
+ for (;;)
+ {
+ float t = Mathf.Min(1f, time / 0.6f);
+ this.col.transform.localPosition = Vector3.Lerp(pos, targ, t);
+ this.col.transform.localScale = Vector3.Lerp(Vector3.one * 0.75f, Vector3.one, t);
+ if (time > 0.6f)
+ {
+ break;
+ }
+ yield return null;
+ time += Time.deltaTime;
+ }
+ this.StatusText.Text = "Please swipe card";
+ this.greenLight.color = this.green;
+ this.State = CardSlideGame.TaskStages.Inserted;
+ yield break;
+ }
+}
diff --git a/Client/Assembly-CSharp/ChainBehaviour.cs b/Client/Assembly-CSharp/ChainBehaviour.cs
new file mode 100644
index 0000000..38a5da5
--- /dev/null
+++ b/Client/Assembly-CSharp/ChainBehaviour.cs
@@ -0,0 +1,27 @@
+using System;
+using UnityEngine;
+
+public class ChainBehaviour : MonoBehaviour
+{
+ public FloatRange SwingRange = new FloatRange(0f, 30f);
+
+ public float SwingPeriod = 2f;
+
+ public float swingTime;
+
+ private Vector3 vec;
+
+ public void Awake()
+ {
+ this.swingTime = FloatRange.Next(0f, this.SwingPeriod);
+ this.vec.z = this.SwingRange.Lerp(Mathf.Sin(this.swingTime));
+ base.transform.eulerAngles = this.vec;
+ }
+
+ public void Update()
+ {
+ this.swingTime += Time.deltaTime / this.SwingPeriod;
+ this.vec.z = this.SwingRange.Lerp(Mathf.Sin(this.swingTime * 3.1415927f) / 2f + 0.5f);
+ base.transform.eulerAngles = this.vec;
+ }
+}
diff --git a/Client/Assembly-CSharp/ChatBubble.cs b/Client/Assembly-CSharp/ChatBubble.cs
new file mode 100644
index 0000000..3c26a40
--- /dev/null
+++ b/Client/Assembly-CSharp/ChatBubble.cs
@@ -0,0 +1,83 @@
+using System;
+using UnityEngine;
+
+internal class ChatBubble : PoolableBehavior
+{
+ public SpriteRenderer ChatFace;
+
+ public SpriteRenderer Xmark;
+
+ public SpriteRenderer votedMark;
+
+ public TextRenderer NameText;
+
+ public TextRenderer TextArea;
+
+ public SpriteRenderer Background;
+
+ public void SetLeft()
+ {
+ base.transform.localPosition = new Vector3(-3f, 0f, 0f);
+ this.ChatFace.flipX = false;
+ this.ChatFace.transform.localScale = new Vector3(1f, 1f, 1f);
+ this.ChatFace.transform.localPosition = new Vector3(0f, 0.07f, 0f);
+ this.Xmark.transform.localPosition = new Vector3(-0.15f, -0.13f, -0.0001f);
+ this.votedMark.transform.localPosition = new Vector3(-0.15f, -0.13f, -0.0001f);
+ this.NameText.transform.localPosition = new Vector3(0.5f, 0.34f, 0f);
+ this.NameText.RightAligned = false;
+ this.TextArea.transform.localPosition = new Vector3(0.5f, 0.09f, 0f);
+ this.TextArea.RightAligned = false;
+ }
+
+ public void SetNotification()
+ {
+ base.transform.localPosition = new Vector3(-2.75f, 0f, 0f);
+ this.ChatFace.flipX = false;
+ this.ChatFace.transform.localScale = new Vector3(0.75f, 0.75f, 1f);
+ this.ChatFace.transform.localPosition = new Vector3(0f, 0.18f, 0f);
+ this.Xmark.transform.localPosition = new Vector3(-0.15f, -0.13f, -0.0001f);
+ this.votedMark.transform.localPosition = new Vector3(-0.15f, -0.13f, -0.0001f);
+ this.NameText.transform.localPosition = new Vector3(0.5f, 0.34f, 0f);
+ this.NameText.RightAligned = false;
+ this.TextArea.transform.localPosition = new Vector3(0.5f, 0.09f, 0f);
+ this.TextArea.RightAligned = false;
+ this.TextArea.Text = string.Empty;
+ }
+
+ public void SetRight()
+ {
+ base.transform.localPosition = new Vector3(-2.35f, 0f, 0f);
+ this.ChatFace.flipX = true;
+ this.ChatFace.transform.localScale = new Vector3(1f, 1f, 1f);
+ this.ChatFace.transform.localPosition = new Vector3(4.75f, 0.07f, 0f);
+ this.Xmark.transform.localPosition = new Vector3(0.15f, -0.13f, -0.0001f);
+ this.votedMark.transform.localPosition = new Vector3(0.15f, -0.13f, -0.0001f);
+ this.NameText.transform.localPosition = new Vector3(4.35f, 0.34f, 0f);
+ this.NameText.RightAligned = true;
+ this.TextArea.transform.localPosition = new Vector3(4.35f, 0.09f, 0f);
+ this.TextArea.RightAligned = true;
+ }
+
+ public void SetName(string playerName, bool isDead, bool voted, Color color)
+ {
+ this.NameText.Text = (playerName ?? "...");
+ this.NameText.Color = color;
+ this.NameText.RefreshMesh();
+ if (isDead)
+ {
+ this.Xmark.enabled = true;
+ this.Background.color = Palette.HalfWhite;
+ }
+ if (voted)
+ {
+ this.votedMark.enabled = true;
+ }
+ }
+
+ public override void Reset()
+ {
+ this.Xmark.enabled = false;
+ this.votedMark.enabled = false;
+ this.Background.color = Color.white;
+ }
+}
diff --git a/Client/Assembly-CSharp/ChatController.cs b/Client/Assembly-CSharp/ChatController.cs
new file mode 100644
index 0000000..3658dd7
--- /dev/null
+++ b/Client/Assembly-CSharp/ChatController.cs
@@ -0,0 +1,326 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class ChatController : MonoBehaviour
+{
+ public bool IsOpen
+ {
+ get
+ {
+ return this.Content.activeInHierarchy;
+ }
+ }
+
+ public ObjectPoolBehavior chatBubPool;
+
+ public Transform TypingArea;
+
+ public SpriteRenderer TextBubble;
+
+ public TextBox TextArea;
+
+ public TextRenderer CharCount;
+
+ public int MaxChat = 15;
+
+ public Scroller scroller;
+
+ public GameObject Content;
+
+ public SpriteRenderer BackgroundImage;
+
+ public SpriteRenderer ChatNotifyDot;
+
+ public TextRenderer SendRateMessage;
+
+ public Vector3 SourcePos = new Vector3(0f, 0f, -10f);
+
+ public Vector3 TargetPos = new Vector3(-0.35f, 0.02f, -10f);
+
+ private const float MaxChatSendRate = 3f;
+
+ private float TimeSinceLastMessage = 3f;
+
+ public AudioClip MessageSound;
+
+ private bool animating;
+
+ private Coroutine notificationRoutine;
+
+ public BanMenu BanButton;
+
+ public void Toggle()
+ {
+ PlayerControl localPlayer = PlayerControl.LocalPlayer;
+ CustomNetworkTransform customNetworkTransform = (localPlayer != null) ? localPlayer.NetTransform : null;
+ if (this.animating || !customNetworkTransform)
+ {
+ return;
+ }
+ base.StopAllCoroutines();
+ if (this.IsOpen)
+ {
+ base.StartCoroutine(this.CoClose());
+ return;
+ }
+ this.Content.SetActive(true);
+ customNetworkTransform.Halt();
+ base.StartCoroutine(this.CoOpen());
+ }
+
+ public void SetVisible(bool visible)
+ {
+ Debug.Log("Chat is hidden: " + visible.ToString());
+ this.ForceClosed();
+ base.gameObject.SetActive(visible);
+ }
+
+ public void ForceClosed()
+ {
+ base.StopAllCoroutines();
+ this.Content.SetActive(false);
+ this.animating = false;
+ }
+
+ public IEnumerator CoOpen()
+ {
+ this.animating = true;
+ Vector3 scale = Vector3.one;
+ this.BanButton.Hide();
+ this.BanButton.SetVisible(true);
+ float targetScale = AspectSize.CalculateSize(base.transform.localPosition, this.BackgroundImage.sprite);
+ float timer = 0f;
+ while (timer < 0.15f)
+ {
+ timer += Time.deltaTime;
+ float num = Mathf.SmoothStep(0f, 1f, timer / 0.15f);
+ scale.y = (scale.x = Mathf.Lerp(0.1f, targetScale, num));
+ this.Content.transform.localScale = scale;
+ this.Content.transform.localPosition = Vector3.Lerp(this.SourcePos, this.TargetPos, num) * targetScale;
+ this.BanButton.transform.localPosition = new Vector3(0f, -num * 0.75f, -20f);
+ yield return null;
+ }
+ this.ChatNotifyDot.enabled = false;
+ this.animating = false;
+ this.GiveFocus();
+ yield break;
+ }
+
+ public IEnumerator CoClose()
+ {
+ this.animating = true;
+ this.BanButton.Hide();
+ Vector3 scale = Vector3.one;
+ float targetScale = AspectSize.CalculateSize(base.transform.localPosition, this.BackgroundImage.sprite);
+ for (float timer = 0f; timer < 0.15f; timer += Time.deltaTime)
+ {
+ float num = 1f - Mathf.SmoothStep(0f, 1f, timer / 0.15f);
+ scale.y = (scale.x = Mathf.Lerp(0.1f, targetScale, num));
+ this.Content.transform.localScale = scale;
+ this.Content.transform.localPosition = Vector3.Lerp(this.SourcePos, this.TargetPos, num) * targetScale;
+ this.BanButton.transform.localPosition = new Vector3(0f, -num * 0.75f, -20f);
+ yield return null;
+ }
+ this.BanButton.SetVisible(false);
+ this.Content.SetActive(false);
+ this.animating = false;
+ yield break;
+ }
+
+ public void SetPosition(MeetingHud meeting)
+ {
+ if (meeting)
+ {
+ base.transform.SetParent(meeting.transform);
+ base.transform.localPosition = new Vector3(3.1f, 2.2f, -10f);
+ return;
+ }
+ base.transform.SetParent(DestroyableSingleton<HudManager>.Instance.transform);
+ base.GetComponent<AspectPosition>().AdjustPosition();
+ }
+
+ public void UpdateCharCount()
+ {
+ Vector2 size = this.TextBubble.size;
+ size.y = Math.Max(0.62f, this.TextArea.TextHeight + 0.2f);
+ this.TextBubble.size = size;
+ Vector3 localPosition = this.TextBubble.transform.localPosition;
+ localPosition.y = (0.62f - size.y) / 2f;
+ this.TextBubble.transform.localPosition = localPosition;
+ Vector3 localPosition2 = this.TypingArea.localPosition;
+ localPosition2.y = -2.08f - localPosition.y * 2f;
+ this.TypingArea.localPosition = localPosition2;
+ int length = this.TextArea.text.Length;
+ this.CharCount.Text = length + "/100";
+ if (length < 75)
+ {
+ this.CharCount.Color = Color.black;
+ return;
+ }
+ if (length < 100)
+ {
+ this.CharCount.Color = new Color(1f, 1f, 0f, 1f);
+ return;
+ }
+ this.CharCount.Color = Color.red;
+ }
+
+ private void Update()
+ {
+ this.TimeSinceLastMessage += Time.deltaTime;
+ if (this.SendRateMessage.isActiveAndEnabled)
+ {
+ float num = 3f - this.TimeSinceLastMessage;
+ if (num < 0f)
+ {
+ this.SendRateMessage.gameObject.SetActive(false);
+ return;
+ }
+ this.SendRateMessage.Text = string.Format("Too fast. Wait {0} seconds", Mathf.CeilToInt(num));
+ }
+ }
+
+ public void SendChat()
+ {
+ float num = 3f - this.TimeSinceLastMessage;
+ if (num > 0f)
+ {
+ this.SendRateMessage.gameObject.SetActive(true);
+ this.SendRateMessage.Text = string.Format("Too fast. Wait {0} seconds", Mathf.CeilToInt(num));
+ return;
+ }
+ if (!PlayerControl.LocalPlayer.RpcSendChat(this.TextArea.text))
+ {
+ return;
+ }
+ this.TimeSinceLastMessage = 0f;
+ this.TextArea.Clear();
+ }
+
+ public void AddChatNote(GameData.PlayerInfo srcPlayer, ChatNoteTypes noteType)
+ {
+ if (srcPlayer == null)
+ {
+ return;
+ }
+ if (this.chatBubPool.NotInUse == 0)
+ {
+ this.chatBubPool.ReclaimOldest();
+ }
+ ChatBubble chatBubble = this.chatBubPool.Get<ChatBubble>();
+ PlayerControl.SetPlayerMaterialColors((int)srcPlayer.ColorId, chatBubble.ChatFace);
+ chatBubble.transform.SetParent(this.scroller.Inner);
+ chatBubble.transform.localScale = Vector3.one;
+ chatBubble.SetNotification();
+ if (noteType == ChatNoteTypes.DidVote)
+ {
+ int votesRemaining = MeetingHud.Instance.GetVotesRemaining();
+ chatBubble.SetName(string.Format("{0} has voted. {1} remaining.", srcPlayer.PlayerName, votesRemaining), false, true, Color.green);
+ }
+ chatBubble.TextArea.RefreshMesh();
+ chatBubble.Background.size = new Vector2(5.52f, 0.2f + chatBubble.NameText.Height);
+ Vector3 localPosition = chatBubble.Background.transform.localPosition;
+ localPosition.y = chatBubble.NameText.transform.localPosition.y - chatBubble.Background.size.y / 2f + 0.05f;
+ chatBubble.Background.transform.localPosition = localPosition;
+ this.AlignAllBubbles();
+ if (!this.IsOpen && this.notificationRoutine == null)
+ {
+ this.notificationRoutine = base.StartCoroutine(this.BounceDot());
+ }
+ if (srcPlayer.Object != PlayerControl.LocalPlayer)
+ {
+ SoundManager.Instance.PlaySound(this.MessageSound, false, 1f).pitch = 0.5f + (float)srcPlayer.PlayerId / 10f;
+ }
+ }
+
+ public void AddChat(PlayerControl sourcePlayer, string chatText)
+ {
+ if (!sourcePlayer || !PlayerControl.LocalPlayer)
+ {
+ return;
+ }
+ GameData.PlayerInfo data = PlayerControl.LocalPlayer.Data;
+ GameData.PlayerInfo data2 = sourcePlayer.Data;
+ if (data2 == null || data == null || (data2.IsDead && !data.IsDead))
+ {
+ return;
+ }
+ if (this.chatBubPool.NotInUse == 0)
+ {
+ this.chatBubPool.ReclaimOldest();
+ }
+ ChatBubble chatBubble = this.chatBubPool.Get<ChatBubble>();
+ try
+ {
+ chatBubble.transform.SetParent(this.scroller.Inner);
+ chatBubble.transform.localScale = Vector3.one;
+ bool flag = sourcePlayer == PlayerControl.LocalPlayer;
+ if (flag)
+ {
+ chatBubble.SetRight();
+ }
+ else
+ {
+ chatBubble.SetLeft();
+ }
+ bool flag2 = data.IsImpostor && data2.IsImpostor;
+ bool voted = MeetingHud.Instance && MeetingHud.Instance.DidVote(sourcePlayer.PlayerId);
+ PlayerControl.SetPlayerMaterialColors((int)data2.ColorId, chatBubble.ChatFace);
+ chatBubble.SetName(data2.PlayerName, data2.IsDead, voted, flag2 ? Palette.ImpostorRed : Color.white);
+ if (SaveManager.CensorChat)
+ {
+ chatText = BlockedWords.CensorWords(chatText);
+ }
+ chatBubble.TextArea.Text = chatText;
+ chatBubble.TextArea.RefreshMesh();
+ chatBubble.Background.size = new Vector2(5.52f, 0.2f + chatBubble.NameText.Height + chatBubble.TextArea.Height);
+ Vector3 localPosition = chatBubble.Background.transform.localPosition;
+ localPosition.y = chatBubble.NameText.transform.localPosition.y - chatBubble.Background.size.y / 2f + 0.05f;
+ chatBubble.Background.transform.localPosition = localPosition;
+ this.AlignAllBubbles();
+ if (!this.IsOpen && this.notificationRoutine == null)
+ {
+ this.notificationRoutine = base.StartCoroutine(this.BounceDot());
+ }
+ if (!flag)
+ {
+ SoundManager.Instance.PlaySound(this.MessageSound, false, 1f).pitch = 0.5f + (float)sourcePlayer.PlayerId / 10f;
+ }
+ }
+ catch
+ {
+ this.chatBubPool.Reclaim(chatBubble);
+ }
+ }
+
+ private void AlignAllBubbles()
+ {
+ float num = 0f;
+ List<PoolableBehavior> activeChildren = this.chatBubPool.activeChildren;
+ for (int i = activeChildren.Count - 1; i >= 0; i--)
+ {
+ ChatBubble chatBubble = activeChildren[i] as ChatBubble;
+ num += chatBubble.Background.size.y;
+ Vector3 localPosition = chatBubble.transform.localPosition;
+ localPosition.y = -1.85f + num;
+ chatBubble.transform.localPosition = localPosition;
+ num += 0.1f;
+ }
+ this.scroller.YBounds.min = Mathf.Min(0f, -num + this.scroller.HitBox.bounds.size.y);
+ }
+
+ private IEnumerator BounceDot()
+ {
+ this.ChatNotifyDot.enabled = true;
+ yield return Effects.Bounce(this.ChatNotifyDot.transform, 0.3f, 0.15f);
+ this.notificationRoutine = null;
+ yield break;
+ }
+
+ public void GiveFocus()
+ {
+ this.TextArea.GiveFocus();
+ }
+}
diff --git a/Client/Assembly-CSharp/ChatNoteTypes.cs b/Client/Assembly-CSharp/ChatNoteTypes.cs
new file mode 100644
index 0000000..c8e3514
--- /dev/null
+++ b/Client/Assembly-CSharp/ChatNoteTypes.cs
@@ -0,0 +1,6 @@
+using System;
+
+public enum ChatNoteTypes
+{
+ DidVote
+}
diff --git a/Client/Assembly-CSharp/CloudGenerator.cs b/Client/Assembly-CSharp/CloudGenerator.cs
new file mode 100644
index 0000000..e2821a2
--- /dev/null
+++ b/Client/Assembly-CSharp/CloudGenerator.cs
@@ -0,0 +1,159 @@
+using System;
+using UnityEngine;
+
+public class CloudGenerator : MonoBehaviour
+{
+ public Sprite[] CloudImages;
+
+ private Vector2[][] UvCache;
+
+ private Vector2[] ExtentCache;
+
+ public int NumClouds = 500;
+
+ public float Length = 25f;
+
+ public float Width = 25f;
+
+ public Vector2 Direction = new Vector2(1f, 0f);
+
+ private Vector2 NormDir = new Vector2(1f, 0f);
+
+ private Vector2 Tangent = new Vector2(0f, 1f);
+
+ private float tanLen;
+
+ public FloatRange Rates = new FloatRange(0.25f, 1f);
+
+ [HideInInspector]
+ private CloudGenerator.Cloud[] stars;
+
+ [HideInInspector]
+ private Vector3[] verts;
+
+ [HideInInspector]
+ private Mesh mesh;
+
+ private struct Cloud
+ {
+ public int CloudIdx;
+
+ public float Rate;
+
+ public float PositionX;
+
+ public float PositionY;
+ }
+
+ public void Start()
+ {
+ this.UvCache = new Vector2[this.CloudImages.Length][];
+ this.ExtentCache = new Vector2[this.CloudImages.Length];
+ for (int i = 0; i < this.CloudImages.Length; i++)
+ {
+ Sprite sprite = this.CloudImages[i];
+ this.UvCache[i] = sprite.uv;
+ this.ExtentCache[i] = sprite.bounds.extents;
+ }
+ this.stars = new CloudGenerator.Cloud[this.NumClouds];
+ this.verts = new Vector3[this.NumClouds * 4];
+ Vector2[] array = new Vector2[this.NumClouds * 4];
+ int[] array2 = new int[this.NumClouds * 6];
+ this.SetDirection(this.Direction);
+ MeshFilter component = base.GetComponent<MeshFilter>();
+ this.mesh = new Mesh();
+ this.mesh.MarkDynamic();
+ component.mesh = this.mesh;
+ Vector3 vector = default(Vector3);
+ for (int j = 0; j < this.stars.Length; j++)
+ {
+ CloudGenerator.Cloud cloud = this.stars[j];
+ int num = cloud.CloudIdx = this.CloudImages.RandomIdx<Sprite>();
+ Vector2 vector2 = this.ExtentCache[num];
+ Vector2[] array3 = this.UvCache[num];
+ float num2 = FloatRange.Next(-1f, 1f) * this.Length;
+ float num3 = FloatRange.Next(-1f, 1f) * this.Width;
+ float num4 = cloud.PositionX = num2 * this.NormDir.x + num3 * this.Tangent.x;
+ float num5 = cloud.PositionY = num2 * this.NormDir.y + num3 * this.Tangent.y;
+ cloud.Rate = this.Rates.Next();
+ this.stars[j] = cloud;
+ int num6 = j * 4;
+ vector.x = num4 - vector2.x;
+ vector.y = num5 + vector2.y;
+ this.verts[num6] = vector;
+ vector.x = num4 + vector2.x;
+ this.verts[num6 + 1] = vector;
+ vector.x = num4 - vector2.x;
+ vector.y = num5 - vector2.y;
+ this.verts[num6 + 2] = vector;
+ vector.x = num4 + vector2.x;
+ this.verts[num6 + 3] = vector;
+ array[num6] = array3[0];
+ array[num6 + 1] = array3[1];
+ array[num6 + 2] = array3[2];
+ array[num6 + 3] = array3[3];
+ int num7 = j * 6;
+ array2[num7] = num6;
+ array2[num7 + 1] = num6 + 1;
+ array2[num7 + 2] = num6 + 2;
+ array2[num7 + 3] = num6 + 2;
+ array2[num7 + 4] = num6 + 1;
+ array2[num7 + 5] = num6 + 3;
+ }
+ this.mesh.vertices = this.verts;
+ this.mesh.uv = array;
+ this.mesh.SetIndices(array2, MeshTopology.Triangles, 0);
+ }
+
+ private void FixedUpdate()
+ {
+ float num = -0.99f * this.Length;
+ Vector2 vector = this.Direction * Time.fixedDeltaTime;
+ Vector3 vector2 = default(Vector3);
+ for (int i = 0; i < this.stars.Length; i++)
+ {
+ int num2 = i * 4;
+ CloudGenerator.Cloud cloud = this.stars[i];
+ float num3 = cloud.PositionX;
+ float num4 = cloud.PositionY;
+ Vector2 vector3 = this.ExtentCache[cloud.CloudIdx];
+ float rate = cloud.Rate;
+ num3 += rate * vector.x;
+ num4 += rate * vector.y;
+ if (this.OrthoDistance(num3, num4) > this.Length)
+ {
+ float num5 = FloatRange.Next(-1f, 1f) * this.Width;
+ num3 = num * this.NormDir.x + num5 * this.Tangent.x;
+ num4 = num * this.NormDir.y + num5 * this.Tangent.y;
+ cloud.Rate = this.Rates.Next();
+ }
+ cloud.PositionX = num3;
+ cloud.PositionY = num4;
+ this.stars[i] = cloud;
+ vector2.x = num3 - vector3.x;
+ vector2.y = num4 + vector3.y;
+ this.verts[num2] = vector2;
+ vector2.x = num3 + vector3.x;
+ this.verts[num2 + 1] = vector2;
+ vector2.x = num3 - vector3.x;
+ vector2.y = num4 - vector3.y;
+ this.verts[num2 + 2] = vector2;
+ vector2.x = num3 + vector3.x;
+ this.verts[num2 + 3] = vector2;
+ }
+ this.mesh.vertices = this.verts;
+ }
+
+ public void SetDirection(Vector2 dir)
+ {
+ this.Direction = dir;
+ this.NormDir = this.Direction.normalized;
+ this.Tangent = new Vector2(-this.NormDir.y, this.NormDir.x);
+ this.tanLen = Mathf.Sqrt(this.Tangent.y * this.Tangent.y + this.Tangent.x * this.Tangent.x);
+ }
+
+ private float OrthoDistance(float pointx, float pointy)
+ {
+ return (this.Tangent.y * pointx - this.Tangent.x * pointy) / this.tanLen;
+ }
+}
diff --git a/Client/Assembly-CSharp/ColorChip.cs b/Client/Assembly-CSharp/ColorChip.cs
new file mode 100644
index 0000000..7f61630
--- /dev/null
+++ b/Client/Assembly-CSharp/ColorChip.cs
@@ -0,0 +1,11 @@
+using System;
+using UnityEngine;
+
+public class ColorChip : MonoBehaviour
+{
+ public SpriteRenderer Inner;
+
+ public GameObject InUseForeground;
+
+ public PassiveButton Button;
+}
diff --git a/Client/Assembly-CSharp/ConditionalHide.cs b/Client/Assembly-CSharp/ConditionalHide.cs
new file mode 100644
index 0000000..5915f4f
--- /dev/null
+++ b/Client/Assembly-CSharp/ConditionalHide.cs
@@ -0,0 +1,21 @@
+using System;
+using UnityEngine;
+
+public class ConditionalHide : MonoBehaviour
+{
+ public RuntimePlatform[] HideForPlatforms = new RuntimePlatform[]
+ {
+ RuntimePlatform.WindowsPlayer
+ };
+
+ private void Awake()
+ {
+ for (int i = 0; i < this.HideForPlatforms.Length; i++)
+ {
+ if (this.HideForPlatforms[i] == RuntimePlatform.WindowsPlayer)
+ {
+ base.gameObject.SetActive(false);
+ }
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/ConditionalStore.cs b/Client/Assembly-CSharp/ConditionalStore.cs
new file mode 100644
index 0000000..c549bff
--- /dev/null
+++ b/Client/Assembly-CSharp/ConditionalStore.cs
@@ -0,0 +1,9 @@
+using System;
+using UnityEngine;
+
+public class ConditionalStore : MonoBehaviour
+{
+ private void Awake()
+ {
+ }
+}
diff --git a/Client/Assembly-CSharp/Console.cs b/Client/Assembly-CSharp/Console.cs
new file mode 100644
index 0000000..31f9aca
--- /dev/null
+++ b/Client/Assembly-CSharp/Console.cs
@@ -0,0 +1,97 @@
+using System;
+using Assets.CoreScripts;
+using UnityEngine;
+
+public class Console : MonoBehaviour, IUsable
+{
+ public float UsableDistance
+ {
+ get
+ {
+ return this.usableDistance;
+ }
+ }
+
+ public float PercentCool
+ {
+ get
+ {
+ return 0f;
+ }
+ }
+
+ public float usableDistance = 1f;
+
+ public int ConsoleId;
+
+ public bool onlyFromBelow;
+
+ public bool GhostsIgnored;
+
+ public SystemTypes Room;
+
+ public TaskTypes[] TaskTypes;
+
+ public TaskSet[] ValidTasks;
+
+ public SpriteRenderer Image;
+
+ public void SetOutline(bool on, bool mainTarget)
+ {
+ if (this.Image)
+ {
+ this.Image.material.SetFloat("_Outline", (float)(on ? 1 : 0));
+ this.Image.material.SetColor("_OutlineColor", Color.yellow);
+ this.Image.material.SetColor("_AddColor", mainTarget ? Color.yellow : Color.clear);
+ }
+ }
+
+ public float CanUse(GameData.PlayerInfo pc, out bool canUse, out bool couldUse)
+ {
+ float num = float.MaxValue;
+ PlayerControl @object = pc.Object;
+ couldUse = ((!pc.IsDead || (PlayerControl.GameOptions.GhostsDoTasks && !this.GhostsIgnored)) && @object.CanMove && !pc.IsImpostor && (!this.onlyFromBelow || @object.transform.position.y < base.transform.position.y) && this.FindTask(@object));
+ canUse = couldUse;
+ if (canUse)
+ {
+ num = Vector2.Distance(@object.GetTruePosition(), base.transform.position);
+ canUse &= (num <= this.UsableDistance);
+ }
+ return num;
+ }
+
+ private PlayerTask FindTask(PlayerControl pc)
+ {
+ for (int i = 0; i < pc.myTasks.Count; i++)
+ {
+ PlayerTask playerTask = pc.myTasks[i];
+ if (!playerTask.IsComplete && playerTask.ValidConsole(this))
+ {
+ return playerTask;
+ }
+ }
+ return null;
+ }
+
+ public void Use()
+ {
+ bool flag;
+ bool flag2;
+ this.CanUse(PlayerControl.LocalPlayer.Data, out flag, out flag2);
+ if (!flag)
+ {
+ return;
+ }
+ PlayerControl localPlayer = PlayerControl.LocalPlayer;
+ PlayerTask playerTask = this.FindTask(localPlayer);
+ if (playerTask.MinigamePrefab)
+ {
+ Minigame minigame = UnityEngine.Object.Instantiate<Minigame>(playerTask.MinigamePrefab);
+ minigame.transform.SetParent(Camera.main.transform, false);
+ minigame.transform.localPosition = new Vector3(0f, 0f, -50f);
+ minigame.Console = this;
+ minigame.Begin(playerTask);
+ DestroyableSingleton<Telemetry>.Instance.WriteUse(localPlayer.PlayerId, playerTask.TaskType, base.transform.position);
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/Constants.cs b/Client/Assembly-CSharp/Constants.cs
new file mode 100644
index 0000000..5daa994
--- /dev/null
+++ b/Client/Assembly-CSharp/Constants.cs
@@ -0,0 +1,90 @@
+using System;
+using UnityEngine;
+
+public static class Constants
+{
+ public const string LocalNetAddress = "127.0.0.1";
+
+ public const int GamePlayPort = 22023;
+
+ public const int AnnouncementPort = 22024;
+
+ public const int ServersPort = 22025;
+
+ public const string InfinitySymbol = "∞";
+
+ public static readonly int ShipOnlyMask = LayerMask.GetMask(new string[]
+ {
+ "Ship"
+ });
+
+ public static readonly int ShipAndObjectsMask = LayerMask.GetMask(new string[]
+ {
+ "Ship",
+ "Objects"
+ });
+
+ public static readonly int ShipAndAllObjectsMask = LayerMask.GetMask(new string[]
+ {
+ "Ship",
+ "Objects",
+ "ShortObjects"
+ });
+
+ public static readonly int NotShipMask = ~LayerMask.GetMask(new string[]
+ {
+ "Ship"
+ });
+
+ public static readonly int Usables = ~LayerMask.GetMask(new string[]
+ {
+ "Ship",
+ "UI"
+ });
+
+ public static readonly int PlayersOnlyMask = LayerMask.GetMask(new string[]
+ {
+ "Players",
+ "Ghost"
+ });
+
+ public static readonly int ShadowMask = LayerMask.GetMask(new string[]
+ {
+ "Shadow",
+ "Objects",
+ "IlluminatedBlocking"
+ });
+
+ public static readonly int[] CompatVersions = new int[]
+ {
+ Constants.GetBroadcastVersion()
+ };
+
+ public const int Year = 2019;
+
+ public const int Month = 6;
+
+ public const int Day = 27;
+
+ public const int Revision = 0;
+
+ internal static int GetBroadcastVersion()
+ {
+ return 50487150;
+ }
+
+ internal static int GetVersion(int year, int month, int day, int rev)
+ {
+ return year * 25000 + month * 1800 + day * 50 + rev;
+ }
+
+ internal static byte[] GetBroadcastVersionBytes()
+ {
+ return BitConverter.GetBytes(Constants.GetBroadcastVersion());
+ }
+
+ public static bool ShouldPlaySfx()
+ {
+ return !AmongUsClient.Instance || AmongUsClient.Instance.GameMode != GameModes.LocalGame || DetectHeadset.Detect();
+ }
+}
diff --git a/Client/Assembly-CSharp/Controller.cs b/Client/Assembly-CSharp/Controller.cs
new file mode 100644
index 0000000..fd84caa
--- /dev/null
+++ b/Client/Assembly-CSharp/Controller.cs
@@ -0,0 +1,157 @@
+using System;
+using UnityEngine;
+
+public class Controller
+{
+ public bool AnyTouch
+ {
+ get
+ {
+ return this.Touches[0].IsDown || this.Touches[1].IsDown;
+ }
+ }
+
+ public bool AnyTouchDown
+ {
+ get
+ {
+ return this.Touches[0].TouchStart || this.Touches[1].TouchStart;
+ }
+ }
+
+ public bool AnyTouchUp
+ {
+ get
+ {
+ return this.Touches[0].TouchEnd || this.Touches[1].TouchEnd;
+ }
+ }
+
+ public bool FirstDown
+ {
+ get
+ {
+ return this.Touches[0].TouchStart;
+ }
+ }
+
+ public Vector2 DragPosition
+ {
+ get
+ {
+ return this.Touches[this.touchId].Position;
+ }
+ }
+
+ public Vector2 DragStartPosition
+ {
+ get
+ {
+ return this.Touches[this.touchId].DownAt;
+ }
+ }
+
+ public readonly Controller.TouchState[] Touches = new Controller.TouchState[2];
+
+ private Collider2D amTouching;
+
+ private int touchId = -1;
+
+ public class TouchState
+ {
+ public Vector2 DownAt;
+
+ public Vector2 Position;
+
+ public bool WasDown;
+
+ public bool IsDown;
+
+ public bool TouchStart;
+
+ public bool TouchEnd;
+ }
+
+ public Controller()
+ {
+ for (int i = 0; i < this.Touches.Length; i++)
+ {
+ this.Touches[i] = new Controller.TouchState();
+ }
+ }
+
+ public DragState CheckDrag(Collider2D coll, bool firstOnly = false)
+ {
+ if (!coll)
+ {
+ return DragState.NoTouch;
+ }
+ if (this.touchId <= -1)
+ {
+ if (firstOnly)
+ {
+ Controller.TouchState touchState = this.Touches[0];
+ if (touchState.TouchStart && coll.OverlapPoint(touchState.Position))
+ {
+ this.amTouching = coll;
+ this.touchId = 0;
+ return DragState.TouchStart;
+ }
+ }
+ else
+ {
+ for (int i = 0; i < this.Touches.Length; i++)
+ {
+ Controller.TouchState touchState2 = this.Touches[i];
+ if (touchState2.TouchStart && coll.OverlapPoint(touchState2.Position))
+ {
+ this.amTouching = coll;
+ this.touchId = i;
+ return DragState.TouchStart;
+ }
+ }
+ }
+ return DragState.NoTouch;
+ }
+ if (coll != this.amTouching)
+ {
+ return DragState.NoTouch;
+ }
+ if (this.Touches[this.touchId].IsDown)
+ {
+ return DragState.Dragging;
+ }
+ this.amTouching = null;
+ this.touchId = -1;
+ return DragState.Released;
+ }
+
+ public void Update()
+ {
+ Controller.TouchState touchState = this.Touches[0];
+ bool mouseButton = Input.GetMouseButton(0);
+ touchState.Position = Camera.main.ScreenToWorldPoint(Input.mousePosition);
+ touchState.TouchStart = (!touchState.IsDown && mouseButton);
+ if (touchState.TouchStart)
+ {
+ touchState.DownAt = touchState.Position;
+ }
+ touchState.TouchEnd = (touchState.IsDown && !mouseButton);
+ touchState.IsDown = mouseButton;
+ }
+
+ public void Reset()
+ {
+ for (int i = 0; i < this.Touches.Length; i++)
+ {
+ this.Touches[i] = new Controller.TouchState();
+ }
+ this.touchId = -1;
+ this.amTouching = null;
+ }
+
+ public Controller.TouchState GetTouch(int i)
+ {
+ return this.Touches[i];
+ }
+}
diff --git a/Client/Assembly-CSharp/CooldownHelpers.cs b/Client/Assembly-CSharp/CooldownHelpers.cs
new file mode 100644
index 0000000..5177c2c
--- /dev/null
+++ b/Client/Assembly-CSharp/CooldownHelpers.cs
@@ -0,0 +1,33 @@
+using System;
+using UnityEngine;
+
+public static class CooldownHelpers
+{
+ public static void SetCooldownNormalizedUvs(this SpriteRenderer myRend)
+ {
+ Vector2[] uv = myRend.sprite.uv;
+ Vector4 vector = new Vector4(2f, -1f, 2f, -1f);
+ for (int i = 0; i < uv.Length; i++)
+ {
+ if (vector.x > uv[i].x)
+ {
+ vector.x = uv[i].x;
+ }
+ if (vector.y < uv[i].x)
+ {
+ vector.y = uv[i].x;
+ }
+ if (vector.z > uv[i].y)
+ {
+ vector.z = uv[i].y;
+ }
+ if (vector.w < uv[i].y)
+ {
+ vector.w = uv[i].y;
+ }
+ }
+ vector.y -= vector.x;
+ vector.w -= vector.z;
+ myRend.material.SetVector("_NormalizedUvs", vector);
+ }
+}
diff --git a/Client/Assembly-CSharp/CounterArea.cs b/Client/Assembly-CSharp/CounterArea.cs
new file mode 100644
index 0000000..c399165
--- /dev/null
+++ b/Client/Assembly-CSharp/CounterArea.cs
@@ -0,0 +1,44 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class CounterArea : MonoBehaviour
+{
+ public SystemTypes RoomType;
+
+ public ObjectPoolBehavior pool;
+
+ private List<PoolableBehavior> myIcons = new List<PoolableBehavior>();
+
+ public float XOffset;
+
+ public float YOffset;
+
+ public int MaxWidth = 5;
+
+ public void UpdateCount(int cnt)
+ {
+ bool flag = this.myIcons.Count != cnt;
+ while (this.myIcons.Count < cnt)
+ {
+ PoolableBehavior item = this.pool.Get<PoolableBehavior>();
+ this.myIcons.Add(item);
+ }
+ while (this.myIcons.Count > cnt)
+ {
+ PoolableBehavior poolableBehavior = this.myIcons[this.myIcons.Count - 1];
+ this.myIcons.RemoveAt(this.myIcons.Count - 1);
+ poolableBehavior.OwnerPool.Reclaim(poolableBehavior);
+ }
+ if (flag)
+ {
+ for (int i = 0; i < this.myIcons.Count; i++)
+ {
+ int num = i % 5;
+ int num2 = i / 5;
+ float num3 = (float)(Mathf.Min(cnt - num2 * 5, 5) - 1) * this.XOffset / -2f;
+ this.myIcons[i].transform.position = base.transform.position + new Vector3(num3 + (float)num * this.XOffset, (float)num2 * this.YOffset, -1f);
+ }
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/CourseMinigame.cs b/Client/Assembly-CSharp/CourseMinigame.cs
new file mode 100644
index 0000000..562074b
--- /dev/null
+++ b/Client/Assembly-CSharp/CourseMinigame.cs
@@ -0,0 +1,206 @@
+using System;
+using System.Runtime.InteropServices;
+using UnityEngine;
+
+public class CourseMinigame : Minigame
+{
+ public CourseStarBehaviour StarPrefab;
+
+ public CourseStarBehaviour[] Stars;
+
+ public SpriteRenderer DotPrefab;
+
+ public Sprite DotLight;
+
+ public SpriteRenderer[] Dots;
+
+ public Collider2D Ship;
+
+ public CourseStarBehaviour Destination;
+
+ public Vector3[] PathPoints;
+
+ public int NumPoints;
+
+ public FloatRange XRange;
+
+ public FloatRange YRange;
+
+ public LineRenderer Path;
+
+ public Controller myController = new Controller();
+
+ public float lineTimer;
+
+ private CourseMinigame.UIntFloat Converter;
+
+ public AudioClip SetCourseSound;
+
+ public AudioClip SetCourseLastSound;
+
+ [StructLayout(LayoutKind.Explicit)]
+ private struct UIntFloat
+ {
+ [FieldOffset(0)]
+ public float FloatValue;
+
+ [FieldOffset(0)]
+ public int IntValue;
+
+ public float GetFloat(byte[] bytes)
+ {
+ this.IntValue = ((int)bytes[0] | (int)bytes[1] << 8 | (int)bytes[2] << 16 | (int)bytes[3] << 24);
+ return this.FloatValue;
+ }
+
+ public void GetBytes(float value, byte[] bytes)
+ {
+ this.FloatValue = value;
+ bytes[0] = (byte)(this.IntValue & 255);
+ bytes[1] = (byte)(this.IntValue >> 8 & 255);
+ bytes[2] = (byte)(this.IntValue >> 16 & 255);
+ bytes[3] = (byte)(this.IntValue >> 24 & 255);
+ }
+ }
+
+ public override void Begin(PlayerTask task)
+ {
+ base.Begin(task);
+ this.PathPoints = new Vector3[this.NumPoints];
+ this.Stars = new CourseStarBehaviour[this.NumPoints];
+ this.Dots = new SpriteRenderer[this.NumPoints];
+ for (int i = 0; i < this.PathPoints.Length; i++)
+ {
+ this.PathPoints[i].x = this.XRange.Lerp((float)i / ((float)this.PathPoints.Length - 1f));
+ do
+ {
+ this.PathPoints[i].y = this.YRange.Next();
+ }
+ while (i > 0 && Mathf.Abs(this.PathPoints[i - 1].y - this.PathPoints[i].y) < this.YRange.Width / 4f);
+ this.Dots[i] = UnityEngine.Object.Instantiate<SpriteRenderer>(this.DotPrefab, base.transform);
+ this.Dots[i].transform.localPosition = this.PathPoints[i];
+ if (i == 0)
+ {
+ this.Dots[i].sprite = this.DotLight;
+ }
+ else
+ {
+ if (i == 1)
+ {
+ this.Ship.transform.localPosition = this.PathPoints[0];
+ this.Ship.transform.eulerAngles = new Vector3(0f, 0f, Vector2.up.AngleSigned(this.PathPoints[1] - this.PathPoints[0]));
+ }
+ this.Stars[i] = UnityEngine.Object.Instantiate<CourseStarBehaviour>(this.StarPrefab, base.transform);
+ this.Stars[i].transform.localPosition = this.PathPoints[i];
+ if (i == this.PathPoints.Length - 1)
+ {
+ this.Destination.transform.localPosition = this.PathPoints[i];
+ }
+ }
+ }
+ this.Path.positionCount = this.PathPoints.Length;
+ this.Path.SetPositions(this.PathPoints);
+ }
+
+ public void FixedUpdate()
+ {
+ float num = this.Converter.GetFloat(this.MyNormTask.Data);
+ int num2 = (int)num;
+ Vector2 b = this.PathPoints[num2];
+ this.myController.Update();
+ DragState dragState = this.myController.CheckDrag(this.Ship, false);
+ if (dragState != DragState.NoTouch)
+ {
+ if (dragState == DragState.Dragging)
+ {
+ if (num < (float)(this.PathPoints.Length - 1))
+ {
+ Vector2 vector = this.PathPoints[num2 + 1] - b;
+ Vector2 a = new Vector2(1f, vector.y / vector.x);
+ Vector2 vector2 = base.transform.InverseTransformPoint(this.myController.DragPosition) - b;
+ if (vector2.x > 0f)
+ {
+ Vector2 vector3 = a * vector2.x;
+ if (Mathf.Abs(vector3.y - vector2.y) < 0.5f)
+ {
+ num = (float)num2 + Mathf.Min(1f, vector2.x / vector.x);
+ Vector3 localPosition = vector3 + b;
+ localPosition.z = -1f;
+ this.Ship.transform.localPosition = localPosition;
+ this.Ship.transform.localPosition = localPosition;
+ this.Ship.transform.eulerAngles = new Vector3(0f, 0f, Vector2.up.AngleSigned(vector));
+ }
+ else
+ {
+ this.myController.Reset();
+ }
+ }
+ }
+ else
+ {
+ Vector3 localPosition2 = this.PathPoints[this.PathPoints.Length - 1];
+ localPosition2.z = -1f;
+ this.Ship.transform.localPosition = localPosition2;
+ }
+ }
+ }
+ else if (num < (float)(this.PathPoints.Length - 1))
+ {
+ Vector2 vector4 = this.PathPoints[num2 + 1] - b;
+ Vector2 a2 = new Vector2(1f, vector4.y / vector4.x);
+ num = Mathf.Max((float)num2, Mathf.Lerp(num, (float)num2, Time.deltaTime * 5f));
+ Vector3 localPosition3 = a2 * (num - (float)num2) + b;
+ localPosition3.z = -1f;
+ this.Ship.transform.localPosition = localPosition3;
+ }
+ else
+ {
+ Vector3 localPosition4 = this.PathPoints[this.PathPoints.Length - 1];
+ localPosition4.z = -1f;
+ this.Ship.transform.localPosition = localPosition4;
+ }
+ if ((int)num > num2 && this.Stars[num2 + 1])
+ {
+ UnityEngine.Object.Destroy(this.Stars[num2 + 1].gameObject);
+ this.Dots[num2 + 1].sprite = this.DotLight;
+ if (num2 == this.PathPoints.Length - 2)
+ {
+ if (Constants.ShouldPlaySfx())
+ {
+ SoundManager.Instance.PlaySound(this.SetCourseLastSound, false, 1f).volume = 0.7f;
+ }
+ this.Destination.Speed *= 5f;
+ this.MyNormTask.NextStep();
+ base.StartCoroutine(base.CoStartClose(0.75f));
+ }
+ else if (Constants.ShouldPlaySfx())
+ {
+ SoundManager.Instance.PlaySound(this.SetCourseSound, false, 1f).volume = 0.7f;
+ }
+ }
+ this.Converter.GetBytes(num, this.MyNormTask.Data);
+ this.SetLineDivision(num);
+ }
+
+ private void SetLineDivision(float curVec)
+ {
+ int num = (int)curVec;
+ float num2 = 0f;
+ int num3 = 0;
+ while ((float)num3 <= curVec && num3 < this.PathPoints.Length - 1)
+ {
+ float num4 = Vector2.Distance(this.PathPoints[num3], this.PathPoints[num3 + 1]);
+ if (num3 == num)
+ {
+ num4 *= curVec - (float)num3;
+ }
+ num2 += num4;
+ num3++;
+ }
+ this.lineTimer -= Time.fixedDeltaTime;
+ Vector2 value = new Vector2(this.lineTimer, 0f);
+ this.Path.material.SetTextureOffset("_MainTex", value);
+ this.Path.material.SetTextureOffset("_AltTex", value);
+ this.Path.material.SetFloat("_Perc", num2 + this.lineTimer / 8f);
+ }
+}
diff --git a/Client/Assembly-CSharp/CourseStarBehaviour.cs b/Client/Assembly-CSharp/CourseStarBehaviour.cs
new file mode 100644
index 0000000..2f5dbe9
--- /dev/null
+++ b/Client/Assembly-CSharp/CourseStarBehaviour.cs
@@ -0,0 +1,17 @@
+using System;
+using UnityEngine;
+
+public class CourseStarBehaviour : MonoBehaviour
+{
+ public SpriteRenderer Upper;
+
+ public SpriteRenderer Lower;
+
+ public float Speed = 30f;
+
+ public void Update()
+ {
+ this.Upper.transform.Rotate(0f, 0f, Time.deltaTime * this.Speed);
+ this.Lower.transform.Rotate(0f, 0f, Time.deltaTime * this.Speed);
+ }
+}
diff --git a/Client/Assembly-CSharp/CreateGameOptions.cs b/Client/Assembly-CSharp/CreateGameOptions.cs
new file mode 100644
index 0000000..23251d4
--- /dev/null
+++ b/Client/Assembly-CSharp/CreateGameOptions.cs
@@ -0,0 +1,104 @@
+using System;
+using System.Collections;
+using InnerNet;
+using PowerTools;
+using UnityEngine;
+
+public class CreateGameOptions : MonoBehaviour, IConnectButton
+{
+ public AudioClip IntroMusic;
+
+ public GameObject Content;
+
+ public SpriteRenderer Foreground;
+
+ public SpriteAnim connectIcon;
+
+ public AnimationClip connectClip;
+
+ public void Show()
+ {
+ if (NameTextBehaviour.Instance.ShakeIfInvalid())
+ {
+ return;
+ }
+ if (StatsManager.Instance.AmBanned)
+ {
+ AmongUsClient.Instance.LastDisconnectReason = DisconnectReasons.IntentionalLeaving;
+ DestroyableSingleton<DisconnectPopup>.Instance.Show();
+ return;
+ }
+ base.gameObject.SetActive(true);
+ this.Content.SetActive(false);
+ base.StartCoroutine(this.CoShow());
+ }
+
+ private IEnumerator CoShow()
+ {
+ yield return Effects.ColorFade(this.Foreground, Color.clear, Color.black, 0.1f);
+ this.Content.SetActive(true);
+ yield return Effects.ColorFade(this.Foreground, Color.black, Color.clear, 0.1f);
+ yield break;
+ }
+
+ public void StartIcon()
+ {
+ if (!this.connectIcon)
+ {
+ return;
+ }
+ this.connectIcon.Play(this.connectClip, 1f);
+ }
+
+ public void StopIcon()
+ {
+ if (!this.connectIcon)
+ {
+ return;
+ }
+ this.connectIcon.Stop();
+ this.connectIcon.GetComponent<SpriteRenderer>().sprite = null;
+ }
+
+ public void Hide()
+ {
+ base.StartCoroutine(this.CoHide());
+ }
+
+ private IEnumerator CoHide()
+ {
+ yield return Effects.ColorFade(this.Foreground, Color.clear, Color.black, 0.1f);
+ this.Content.SetActive(false);
+ yield return Effects.ColorFade(this.Foreground, Color.black, Color.clear, 0.1f);
+ base.gameObject.SetActive(false);
+ yield break;
+ }
+
+ public void Confirm()
+ {
+ if (!DestroyableSingleton<MatchMaker>.Instance.Connecting(this))
+ {
+ return;
+ }
+ base.StartCoroutine(this.CoStartGame());
+ }
+
+ private IEnumerator CoStartGame()
+ {
+ SoundManager.Instance.CrossFadeSound("MainBG", null, 0.5f, 1.5f);
+ yield return Effects.ColorFade(this.Foreground, Color.clear, Color.black, 0.2f);
+ AmongUsClient.Instance.GameMode = GameModes.OnlineGame;
+ AmongUsClient.Instance.SetEndpoint(DestroyableSingleton<ServerManager>.Instance.OnlineNetAddress, 22023);
+ AmongUsClient.Instance.MainMenuScene = "MMOnline";
+ AmongUsClient.Instance.OnlineScene = "OnlineGame";
+ AmongUsClient.Instance.Connect(MatchMakerModes.HostAndClient);
+ yield return AmongUsClient.Instance.WaitForConnectionOrFail();
+ DestroyableSingleton<MatchMaker>.Instance.NotConnecting();
+ if (AmongUsClient.Instance.mode == MatchMakerModes.None)
+ {
+ SoundManager.Instance.CrossFadeSound("MainBG", this.IntroMusic, 0.5f, 1.5f);
+ yield return Effects.ColorFade(this.Foreground, Color.black, Color.clear, 0.2f);
+ }
+ yield break;
+ }
+}
diff --git a/Client/Assembly-CSharp/CreateOptionsPicker.cs b/Client/Assembly-CSharp/CreateOptionsPicker.cs
new file mode 100644
index 0000000..9210446
--- /dev/null
+++ b/Client/Assembly-CSharp/CreateOptionsPicker.cs
@@ -0,0 +1,165 @@
+using System;
+using InnerNet;
+using UnityEngine;
+
+public class CreateOptionsPicker : MonoBehaviour
+{
+ public SpriteRenderer[] MaxPlayerButtons;
+
+ public SpriteRenderer[] ImpostorButtons;
+
+ public SpriteRenderer[] LanguageButtons;
+
+ public SpriteRenderer[] MapButtons;
+
+ public SettingsMode mode;
+
+ public CrewVisualizer CrewArea;
+
+ public void Start()
+ {
+ this.MapButtons[1].gameObject.SetActive(false);
+ GameOptionsData targetOptions = this.GetTargetOptions();
+ this.UpdateImpostorsButtons(targetOptions.NumImpostors);
+ this.UpdateMaxPlayersButtons(targetOptions);
+ this.UpdateLanguageButtons(targetOptions.Keywords & GameKeywords.AllLanguages);
+ this.UpdateMapButtons((int)targetOptions.MapId);
+ }
+
+ private GameOptionsData GetTargetOptions()
+ {
+ if (this.mode == SettingsMode.Host)
+ {
+ return SaveManager.GameHostOptions;
+ }
+ GameOptionsData gameSearchOptions = SaveManager.GameSearchOptions;
+ if (gameSearchOptions.MapId == 0)
+ {
+ gameSearchOptions.ToggleMapFilter(0);
+ SaveManager.GameSearchOptions = gameSearchOptions;
+ }
+ return gameSearchOptions;
+ }
+
+ private void SetTargetOptions(GameOptionsData data)
+ {
+ if (this.mode == SettingsMode.Host)
+ {
+ SaveManager.GameHostOptions = data;
+ return;
+ }
+ SaveManager.GameSearchOptions = data;
+ }
+
+ public void SetMaxPlayersButtons(int maxPlayers)
+ {
+ GameOptionsData targetOptions = this.GetTargetOptions();
+ if (maxPlayers < GameOptionsData.MinPlayers[targetOptions.NumImpostors])
+ {
+ return;
+ }
+ targetOptions.MaxPlayers = maxPlayers;
+ this.SetTargetOptions(targetOptions);
+ if (DestroyableSingleton<FindAGameManager>.InstanceExists)
+ {
+ DestroyableSingleton<FindAGameManager>.Instance.ResetTimer();
+ }
+ this.UpdateMaxPlayersButtons(targetOptions);
+ }
+
+ private void UpdateMaxPlayersButtons(GameOptionsData opts)
+ {
+ if (this.CrewArea)
+ {
+ this.CrewArea.SetCrewSize(opts.MaxPlayers, opts.NumImpostors);
+ }
+ for (int i = 0; i < this.MaxPlayerButtons.Length; i++)
+ {
+ SpriteRenderer spriteRenderer = this.MaxPlayerButtons[i];
+ spriteRenderer.enabled = (spriteRenderer.name == opts.MaxPlayers.ToString());
+ spriteRenderer.GetComponentInChildren<TextRenderer>().Color = ((int.Parse(spriteRenderer.name) < GameOptionsData.MinPlayers[opts.NumImpostors]) ? Palette.DisabledGrey : Color.white);
+ }
+ }
+
+ public void SetImpostorButtons(int numImpostors)
+ {
+ GameOptionsData targetOptions = this.GetTargetOptions();
+ targetOptions.NumImpostors = numImpostors;
+ this.SetTargetOptions(targetOptions);
+ this.SetMaxPlayersButtons(Mathf.Max(targetOptions.MaxPlayers, GameOptionsData.MinPlayers[numImpostors]));
+ this.UpdateImpostorsButtons(numImpostors);
+ }
+
+ private void UpdateImpostorsButtons(int numImpostors)
+ {
+ for (int i = 0; i < this.ImpostorButtons.Length; i++)
+ {
+ SpriteRenderer spriteRenderer = this.ImpostorButtons[i];
+ spriteRenderer.enabled = (spriteRenderer.name == numImpostors.ToString());
+ }
+ }
+
+ public void SetMap(int mapid)
+ {
+ GameOptionsData targetOptions = this.GetTargetOptions();
+ if (this.mode == SettingsMode.Host)
+ {
+ targetOptions.MapId = (byte)mapid;
+ }
+ else
+ {
+ targetOptions.ToggleMapFilter((byte)mapid);
+ }
+ this.SetTargetOptions(targetOptions);
+ if (DestroyableSingleton<FindAGameManager>.InstanceExists)
+ {
+ DestroyableSingleton<FindAGameManager>.Instance.ResetTimer();
+ }
+ this.UpdateMapButtons(mapid);
+ }
+
+ private void UpdateMapButtons(int mapid)
+ {
+ if (this.mode == SettingsMode.Host)
+ {
+ if (this.CrewArea)
+ {
+ this.CrewArea.SetMap(mapid);
+ }
+ for (int i = 0; i < this.MapButtons.Length; i++)
+ {
+ SpriteRenderer spriteRenderer = this.MapButtons[i];
+ spriteRenderer.color = ((spriteRenderer.name == mapid.ToString()) ? Color.white : Palette.DisabledGrey);
+ }
+ return;
+ }
+ GameOptionsData targetOptions = this.GetTargetOptions();
+ for (int j = 0; j < this.MapButtons.Length; j++)
+ {
+ SpriteRenderer spriteRenderer2 = this.MapButtons[j];
+ spriteRenderer2.color = (targetOptions.FilterContainsMap(byte.Parse(spriteRenderer2.name)) ? Color.white : Palette.DisabledGrey);
+ }
+ }
+
+ public void SetLanguageFilter(int keyword)
+ {
+ GameOptionsData targetOptions = this.GetTargetOptions();
+ targetOptions.Keywords &= ~GameKeywords.AllLanguages;
+ targetOptions.Keywords |= (GameKeywords)keyword;
+ this.SetTargetOptions(targetOptions);
+ if (DestroyableSingleton<FindAGameManager>.InstanceExists)
+ {
+ DestroyableSingleton<FindAGameManager>.Instance.ResetTimer();
+ }
+ this.UpdateLanguageButtons((GameKeywords)keyword);
+ }
+
+ private void UpdateLanguageButtons(GameKeywords button)
+ {
+ for (int i = 0; i < this.LanguageButtons.Length; i++)
+ {
+ SpriteRenderer spriteRenderer = this.LanguageButtons[i];
+ spriteRenderer.enabled = (spriteRenderer.name == button.ToString());
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/CreateStoreButton.cs b/Client/Assembly-CSharp/CreateStoreButton.cs
new file mode 100644
index 0000000..b08c3d5
--- /dev/null
+++ b/Client/Assembly-CSharp/CreateStoreButton.cs
@@ -0,0 +1,16 @@
+using System;
+using UnityEngine;
+
+public class CreateStoreButton : MonoBehaviour
+{
+ public Transform Target;
+
+ public StoreMenu StorePrefab;
+
+ public void Click()
+ {
+ StoreMenu storeMenu = UnityEngine.Object.Instantiate<StoreMenu>(this.StorePrefab, this.Target);
+ storeMenu.transform.localPosition = new Vector3(0f, 0f, -100f);
+ storeMenu.transform.localScale = Vector3.zero;
+ }
+}
diff --git a/Client/Assembly-CSharp/CrewVisualizer.cs b/Client/Assembly-CSharp/CrewVisualizer.cs
new file mode 100644
index 0000000..31e26e7
--- /dev/null
+++ b/Client/Assembly-CSharp/CrewVisualizer.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class CrewVisualizer : MonoBehaviour
+{
+ public ObjectPoolBehavior CrewPool;
+
+ public SpriteRenderer Background;
+
+ public Sprite[] MapBackgrounds;
+
+ public float yOffset = 0.4f;
+
+ public FloatRange BgWidth;
+
+ public void SetCrewSize(int numPlayers, int numImpostors)
+ {
+ this.CrewPool.ReclaimAll();
+ int num = numPlayers / 2;
+ int num2 = Mathf.CeilToInt((float)numPlayers / 2f);
+ List<SpriteRenderer> list = new List<SpriteRenderer>();
+ Vector3 localPosition = new Vector3(0f, 0f, -1f);
+ for (int i = 0; i < numPlayers; i++)
+ {
+ SpriteRenderer component = this.CrewPool.Get<PoolableBehavior>().GetComponent<SpriteRenderer>();
+ component.color = Color.white;
+ list.Add(component);
+ if (i < num)
+ {
+ float num3 = Mathf.Clamp((float)num / 5f * 1.3f, 0f, 1f) * 0.85f;
+ localPosition.z = -1.5f;
+ localPosition.y = -this.yOffset;
+ localPosition.x = this.BgWidth.Lerp((float)i / ((float)num - 1f)) * num3;
+ }
+ else
+ {
+ float num4 = Mathf.Clamp((float)num2 / 5f * 1.3f, 0f, 1f);
+ localPosition.z = -1f;
+ localPosition.y = this.yOffset;
+ localPosition.x = this.BgWidth.Lerp((float)(i - num) / ((float)num2 - 1f)) * num4;
+ }
+ component.transform.localPosition = localPosition;
+ }
+ int j = 0;
+ int num5 = 0;
+ while (j < numImpostors)
+ {
+ if (BoolRange.Next(1f / (float)list.Count))
+ {
+ j++;
+ list[num5].color = Color.red;
+ list.RemoveAt(num5);
+ }
+ num5 = (num5 + 1) % list.Count;
+ }
+ }
+
+ public void SetMap(int mapid)
+ {
+ this.Background.sprite = this.MapBackgrounds[mapid];
+ }
+}
diff --git a/Client/Assembly-CSharp/CrossFadeImages.cs b/Client/Assembly-CSharp/CrossFadeImages.cs
new file mode 100644
index 0000000..912bf23
--- /dev/null
+++ b/Client/Assembly-CSharp/CrossFadeImages.cs
@@ -0,0 +1,20 @@
+using System;
+using UnityEngine;
+
+public class CrossFadeImages : MonoBehaviour
+{
+ public SpriteRenderer Image1;
+
+ public SpriteRenderer Image2;
+
+ public float Period = 5f;
+
+ private void Update()
+ {
+ Color white = Color.white;
+ white.a = Mathf.Clamp((Mathf.Sin(3.1415927f * Time.time / this.Period) + 0.75f) * 0.75f, 0f, 1f);
+ this.Image1.color = white;
+ white.a = 1f - white.a;
+ this.Image2.color = white;
+ }
+}
diff --git a/Client/Assembly-CSharp/CrossFader.cs b/Client/Assembly-CSharp/CrossFader.cs
new file mode 100644
index 0000000..39ccf82
--- /dev/null
+++ b/Client/Assembly-CSharp/CrossFader.cs
@@ -0,0 +1,74 @@
+using System;
+using UnityEngine;
+
+public class CrossFader : ISoundPlayer
+{
+ public string Name { get; set; }
+
+ public AudioSource Player { get; set; }
+
+ public float MaxVolume = 1f;
+
+ public AudioClip target;
+
+ public float Duration = 1.5f;
+
+ private float timer;
+
+ private bool didSwitch;
+
+ public void Update(float dt)
+ {
+ if (this.timer < this.Duration)
+ {
+ this.timer += dt;
+ float num = this.timer / this.Duration;
+ if (num < 0.5f)
+ {
+ this.Player.volume = (1f - num * 2f) * this.MaxVolume;
+ return;
+ }
+ if (!this.didSwitch)
+ {
+ this.didSwitch = true;
+ this.Player.Stop();
+ this.Player.clip = this.target;
+ if (this.target)
+ {
+ this.Player.Play();
+ }
+ }
+ this.Player.volume = (num - 0.5f) * 2f * this.MaxVolume;
+ }
+ }
+
+ public void SetTarget(AudioClip clip)
+ {
+ if (!this.Player.clip)
+ {
+ this.didSwitch = false;
+ this.Player.volume = 0f;
+ this.timer = 0.5f;
+ }
+ else
+ {
+ if (this.Player.clip == clip)
+ {
+ return;
+ }
+ if (this.didSwitch)
+ {
+ this.didSwitch = false;
+ if (this.timer >= this.Duration)
+ {
+ this.timer = 0f;
+ }
+ else
+ {
+ this.timer = this.Duration - this.timer;
+ }
+ }
+ }
+ this.target = clip;
+ }
+}
diff --git a/Client/Assembly-CSharp/CrystalBehaviour.cs b/Client/Assembly-CSharp/CrystalBehaviour.cs
new file mode 100644
index 0000000..ebb7b2b
--- /dev/null
+++ b/Client/Assembly-CSharp/CrystalBehaviour.cs
@@ -0,0 +1,110 @@
+using System;
+using System.Collections;
+using UnityEngine;
+
+public class CrystalBehaviour : MonoBehaviour
+{
+ public CrystalBehaviour Above;
+
+ public CrystalBehaviour Below;
+
+ public CrystalBehaviour.Parentness ParentSide;
+
+ public SpriteRenderer Renderer;
+
+ public BoxCollider2D Collider;
+
+ public FloatRange Padding;
+
+ private const float Speed = 15f;
+
+ private const float FloatMag = 0.05f;
+
+ private const float FloatSpeed = 0.35f;
+
+ public enum Parentness
+ {
+ None,
+ Above,
+ Below
+ }
+
+ private void Update()
+ {
+ Vector3 position = base.transform.position;
+ Vector3 vector;
+ if (this.ParentSide == CrystalBehaviour.Parentness.Above)
+ {
+ if (!this.Above)
+ {
+ return;
+ }
+ vector = this.Above.transform.position - new Vector3(0f, this.Above.Padding.min + this.Padding.max, 0f);
+ }
+ else
+ {
+ if (this.ParentSide != CrystalBehaviour.Parentness.Below)
+ {
+ return;
+ }
+ if (!this.Below)
+ {
+ return;
+ }
+ vector = this.Below.transform.position + new Vector3(0f, this.Below.Padding.max + this.Padding.min, 0f);
+ }
+ float num = Time.time / 0.35f;
+ vector.x += (Mathf.PerlinNoise(num, position.z * 20f) * 2f - 1f) * 0.05f;
+ vector.y += (Mathf.PerlinNoise(position.z * 20f, num) * 2f - 1f) * 0.05f;
+ vector.z = position.z;
+ position.x = Mathf.SmoothStep(position.x, vector.x, Time.deltaTime * 15f);
+ position.y = Mathf.SmoothStep(position.y, vector.y, Time.deltaTime * 15f);
+ base.transform.position = position;
+ }
+
+ public void FlashUp(float delay = 0f)
+ {
+ base.StopAllCoroutines();
+ base.StartCoroutine(CrystalBehaviour.Flash(this, delay));
+ if (this.Above)
+ {
+ this.Above.FlashUp(delay + 0.1f);
+ }
+ }
+
+ public void FlashDown(float delay = 0f)
+ {
+ base.StopAllCoroutines();
+ base.StartCoroutine(CrystalBehaviour.Flash(this, delay));
+ if (this.Below)
+ {
+ this.Below.FlashDown(delay + 0.1f);
+ }
+ }
+
+ private static IEnumerator Flash(CrystalBehaviour c, float delay)
+ {
+ for (float time = 0f; time < delay; time += Time.deltaTime)
+ {
+ yield return null;
+ }
+ Color col = Color.clear;
+ for (float time = 0f; time < 0.1f; time += Time.deltaTime)
+ {
+ float t = time / 0.1f;
+ col.r = (col.g = (col.b = Mathf.Lerp(0f, 1f, t)));
+ c.Renderer.material.SetColor("_AddColor", col);
+ yield return null;
+ }
+ for (float time = 0f; time < 0.1f; time += Time.deltaTime)
+ {
+ float t2 = time / 0.1f;
+ col.r = (col.g = (col.b = Mathf.Lerp(1f, 0f, t2)));
+ c.Renderer.material.SetColor("_AddColor", col);
+ yield return null;
+ }
+ col.r = (col.g = (col.b = 0f));
+ c.Renderer.material.SetColor("_AddColor", col);
+ yield break;
+ }
+}
diff --git a/Client/Assembly-CSharp/CrystalMinigame.cs b/Client/Assembly-CSharp/CrystalMinigame.cs
new file mode 100644
index 0000000..6e749f0
--- /dev/null
+++ b/Client/Assembly-CSharp/CrystalMinigame.cs
@@ -0,0 +1,120 @@
+using System;
+using UnityEngine;
+
+public class CrystalMinigame : Minigame
+{
+ public CrystalBehaviour[] CrystalPieces;
+
+ public FloatRange XRange;
+
+ public FloatRange YRange;
+
+ private Controller myController = new Controller();
+
+ public override void Begin(PlayerTask task)
+ {
+ base.Begin(task);
+ for (int i = 0; i < this.CrystalPieces.Length; i++)
+ {
+ this.CrystalPieces[i].transform.localPosition = new Vector3(this.XRange.Next(), this.YRange.Next(), ((float)i - (float)this.CrystalPieces.Length / 2f) / 100f);
+ }
+ }
+
+ public void Update()
+ {
+ this.myController.Update();
+ for (int i = 0; i < this.CrystalPieces.Length; i++)
+ {
+ CrystalBehaviour crystalBehaviour = this.CrystalPieces[i];
+ switch (this.myController.CheckDrag(crystalBehaviour.Collider, false))
+ {
+ case DragState.TouchStart:
+ this.Spread(i);
+ break;
+ case DragState.Dragging:
+ {
+ Vector3 position = this.myController.DragPosition;
+ position.z = base.transform.position.z;
+ crystalBehaviour.transform.position = position;
+ break;
+ }
+ case DragState.Released:
+ this.CheckSolution();
+ break;
+ }
+ }
+ }
+
+ private void Spread(int parent)
+ {
+ for (int i = 0; i < this.CrystalPieces.Length; i++)
+ {
+ if (i < parent)
+ {
+ this.CrystalPieces[i].ParentSide = CrystalBehaviour.Parentness.Below;
+ }
+ else if (i > parent)
+ {
+ this.CrystalPieces[i].ParentSide = CrystalBehaviour.Parentness.Above;
+ }
+ else
+ {
+ this.CrystalPieces[i].ParentSide = CrystalBehaviour.Parentness.None;
+ }
+ }
+ }
+
+ private void CheckSolution()
+ {
+ bool flag = false;
+ for (int i = 0; i < this.CrystalPieces.Length; i++)
+ {
+ CrystalBehaviour crystalBehaviour = this.CrystalPieces[i];
+ Vector3 position = crystalBehaviour.transform.position;
+ if (!crystalBehaviour.Above && i - 1 > -1)
+ {
+ CrystalBehaviour crystalBehaviour2 = this.CrystalPieces[i - 1];
+ if (CrystalMinigame.AreTouching(crystalBehaviour2.Collider, crystalBehaviour.Collider))
+ {
+ crystalBehaviour.Above = crystalBehaviour2;
+ crystalBehaviour2.Below = crystalBehaviour;
+ crystalBehaviour.FlashUp(0f);
+ }
+ else
+ {
+ flag = true;
+ }
+ }
+ if (!crystalBehaviour.Below && i + 1 < this.CrystalPieces.Length)
+ {
+ CrystalBehaviour crystalBehaviour3 = this.CrystalPieces[i + 1];
+ if (CrystalMinigame.AreTouching(crystalBehaviour3.Collider, crystalBehaviour.Collider))
+ {
+ crystalBehaviour.Below = crystalBehaviour3;
+ crystalBehaviour3.Above = crystalBehaviour;
+ crystalBehaviour.FlashDown(0f);
+ }
+ else
+ {
+ flag = true;
+ }
+ }
+ }
+ if (!flag)
+ {
+ this.MyNormTask.Complete();
+ base.StartCoroutine(base.CoStartClose(0.75f));
+ }
+ }
+
+ private static bool AreTouching(BoxCollider2D a, BoxCollider2D b)
+ {
+ Vector2 a2 = a.transform.position + a.offset;
+ Vector2 a3 = b.transform.position + b.offset;
+ Vector2 vector = a2 - a.size / 2f;
+ Vector2 vector2 = a3 - b.size / 2f;
+ Vector2 vector3 = a2 + a.size / 2f;
+ Vector2 vector4 = a3 + b.size / 2f;
+ return ((vector.y < vector4.y && vector.y > vector2.y) || (vector3.y < vector4.y && vector3.y > vector2.y)) && ((vector.x < vector4.x && vector.x > vector2.x) || (vector3.x < vector4.x && vector3.x > vector2.x));
+ }
+}
diff --git a/Client/Assembly-CSharp/CustomNetworkTransform.cs b/Client/Assembly-CSharp/CustomNetworkTransform.cs
new file mode 100644
index 0000000..98a1969
--- /dev/null
+++ b/Client/Assembly-CSharp/CustomNetworkTransform.cs
@@ -0,0 +1,265 @@
+using System;
+using Hazel;
+using InnerNet;
+using UnityEngine;
+
+//c 角色的位置和速度数据
+[DisallowMultipleComponent]
+public class CustomNetworkTransform : InnerNetObject
+{
+ private const float LocalMovementThreshold = 0.0001f;
+
+ private const float LocalVelocityThreshold = 0.0001f;
+
+ private const float MoveAheadRatio = 0.1f;
+
+ private readonly FloatRange XRange = new FloatRange(-40f, 40f);
+
+ private readonly FloatRange YRange = new FloatRange(-40f, 40f);
+
+ // 用来辅助设置位置
+ [SerializeField]
+ private float sendInterval = 0.1f;
+
+ [SerializeField]
+ private float snapThreshold = 5f;
+
+ [SerializeField]
+ private float interpolateMovement = 1f;
+
+ private Rigidbody2D body;
+
+ private Vector2 targetSyncPosition;
+
+ private Vector2 targetSyncVelocity;
+
+ private ushort lastSequenceId;
+
+ private Vector2 prevPosSent;
+
+ private Vector2 prevVelSent;
+
+ private enum RpcCalls
+ {
+ SnapTo
+ }
+
+ private void Awake()
+ {
+ this.body = base.GetComponent<Rigidbody2D>();
+ this.targetSyncPosition = (this.prevPosSent = base.transform.position);
+ this.targetSyncVelocity = (this.prevVelSent = Vector2.zero);
+ }
+
+ public void OnEnable()
+ {
+ base.SetDirtyBit(3U);
+ }
+
+ public void Halt()
+ {
+ ushort minSid = this.lastSequenceId + 1;
+ this.SnapTo(base.transform.position, minSid);
+ }
+
+ public void RpcSnapTo(Vector2 position)
+ {
+ ushort minSid = this.lastSequenceId + 5;
+ if (AmongUsClient.Instance.AmClient)
+ {
+ this.SnapTo(position, minSid);
+ }
+ MessageWriter messageWriter = AmongUsClient.Instance.StartRpc(this.NetId, 0, SendOption.Reliable);
+ this.WriteVector2(position, messageWriter);
+ messageWriter.Write(this.lastSequenceId);
+ messageWriter.EndMessage();
+ }
+
+ public void SnapTo(Vector2 position)
+ {
+ ushort minSid = this.lastSequenceId + 3;
+ this.SnapTo(position, minSid);
+ }
+
+ private void SnapTo(Vector2 position, ushort minSid)
+ {
+ if (!CustomNetworkTransform.SidGreaterThan(minSid, this.lastSequenceId))
+ {
+ return;
+ }
+ this.lastSequenceId = minSid;
+ Transform transform = base.transform;
+ this.body.position = position;
+ this.targetSyncPosition = position;
+ transform.position = position;
+ this.targetSyncVelocity = (this.body.velocity = Vector2.zero);
+ this.prevPosSent = position;
+ this.prevVelSent = Vector2.zero;
+ }
+
+ private void FixedUpdate()
+ {
+ if (base.AmOwner)
+ {
+ if (this.HasMoved())
+ {
+ base.SetDirtyBit(3U);
+ return;
+ }
+ }
+ else
+ {
+ if (this.interpolateMovement != 0f)
+ {
+ Vector2 vector = this.targetSyncPosition - this.body.position;
+ if (vector.sqrMagnitude >= 0.0001f)
+ {
+ float num = this.interpolateMovement / this.sendInterval;
+ vector.x *= num;
+ vector.y *= num;
+ if (PlayerControl.LocalPlayer)
+ {
+ vector = Vector2.ClampMagnitude(vector, PlayerControl.LocalPlayer.MyPhysics.TrueSpeed);
+ }
+ this.body.velocity = vector;
+ }
+ else
+ {
+ this.body.velocity = Vector2.zero;
+ }
+ }
+ this.targetSyncPosition += this.targetSyncVelocity * Time.fixedDeltaTime * 0.1f;
+ }
+ }
+
+ private bool HasMoved()
+ {
+ float num;
+ if (this.body != null)
+ {
+ num = Vector2.Distance(this.body.position, this.prevPosSent);
+ }
+ else
+ {
+ num = Vector2.Distance(base.transform.position, this.prevPosSent);
+ }
+ if (num > 0.0001f)
+ {
+ return true;
+ }
+ if (this.body != null)
+ {
+ num = Vector2.Distance(this.body.velocity, this.prevVelSent);
+ }
+ return num > 0.0001f;
+ }
+
+ public override void HandleRpc(byte callId, MessageReader reader)
+ {
+ if (!base.isActiveAndEnabled)
+ {
+ return;
+ }
+ if (callId == 0)
+ {
+ Vector2 position = this.ReadVector2(reader);
+ ushort minSid = reader.ReadUInt16();
+ this.SnapTo(position, minSid);
+ }
+ }
+
+ //c 序列化角色位置数据
+ public override bool Serialize(MessageWriter writer, bool initialState)
+ {
+ if (initialState)
+ {
+ writer.Write(this.lastSequenceId);
+ this.WriteVector2(this.body.position, writer);
+ this.WriteVector2(this.body.velocity, writer);
+ return true;
+ }
+ if (this.DirtyBits == 0U)
+ {
+ return false;
+ }
+ if (!base.isActiveAndEnabled)
+ {
+ this.DirtyBits = 0U;
+ return false;
+ }
+ this.lastSequenceId += 1;
+ writer.Write(this.lastSequenceId);
+ this.WriteVector2(this.body.position, writer);
+ this.WriteVector2(this.body.velocity, writer);
+ this.prevPosSent = this.body.position;
+ this.prevVelSent = this.body.velocity;
+ this.DirtyBits -= 1U;
+ return true;
+ }
+
+ //c 反序列化角色数据
+ public override void Deserialize(MessageReader reader, bool initialState)
+ {
+ if (initialState)
+ {
+ this.lastSequenceId = reader.ReadUInt16();
+ this.targetSyncPosition = (base.transform.position = this.ReadVector2(reader));
+ this.targetSyncVelocity = this.ReadVector2(reader);
+ return;
+ }
+ ushort newSid = reader.ReadUInt16();
+ if (!CustomNetworkTransform.SidGreaterThan(newSid, this.lastSequenceId))
+ {
+ return;
+ }
+ this.lastSequenceId = newSid;
+ if (!base.isActiveAndEnabled)
+ {
+ return;
+ }
+ this.targetSyncPosition = this.ReadVector2(reader);
+ this.targetSyncVelocity = this.ReadVector2(reader);
+ // 当本地计算的位置数据和网络传输的位置数据差别大于snapThreshold的时候直接用消息里的位置和速度数据
+ if (Vector2.Distance(this.body.position, this.targetSyncPosition) > this.snapThreshold)
+ {
+ if (this.body)
+ {
+ this.body.position = this.targetSyncPosition;
+ this.body.velocity = this.targetSyncVelocity;
+ }
+ else
+ {
+ base.transform.position = this.targetSyncPosition;
+ }
+ }
+ if (this.interpolateMovement == 0f && this.body)
+ {
+ this.body.position = this.targetSyncPosition;
+ }
+ }
+
+ private static bool SidGreaterThan(ushort newSid, ushort prevSid)
+ {
+ ushort num = prevSid + 32767;
+ if (prevSid < num)
+ {
+ return newSid > prevSid && newSid <= num;
+ }
+ return newSid > prevSid || newSid <= num;
+ }
+
+ private void WriteVector2(Vector2 vec, MessageWriter writer)
+ {
+ ushort value = (ushort)(this.XRange.ReverseLerp(vec.x) * 65535f);
+ ushort value2 = (ushort)(this.YRange.ReverseLerp(vec.y) * 65535f);
+ writer.Write(value);
+ writer.Write(value2);
+ }
+
+ private Vector2 ReadVector2(MessageReader reader)
+ {
+ float v = (float)reader.ReadUInt16() / 65535f;
+ float v2 = (float)reader.ReadUInt16() / 65535f;
+ return new Vector2(this.XRange.Lerp(v), this.YRange.Lerp(v2));
+ }
+}
diff --git a/Client/Assembly-CSharp/CustomPlayerMenu.cs b/Client/Assembly-CSharp/CustomPlayerMenu.cs
new file mode 100644
index 0000000..9213223
--- /dev/null
+++ b/Client/Assembly-CSharp/CustomPlayerMenu.cs
@@ -0,0 +1,41 @@
+using System;
+using UnityEngine;
+
+public class CustomPlayerMenu : MonoBehaviour
+{
+ public static CustomPlayerMenu Instance;
+
+ public TabButton[] Tabs;
+
+ public Sprite NormalColor;
+
+ public Sprite SelectedColor;
+
+ public void Start()
+ {
+ CustomPlayerMenu.Instance = this;
+ }
+
+ public void OpenTab(GameObject tab)
+ {
+ for (int i = 0; i < this.Tabs.Length; i++)
+ {
+ TabButton tabButton = this.Tabs[i];
+ if (tabButton.Tab == tab)
+ {
+ tabButton.Tab.SetActive(true);
+ tabButton.Button.sprite = this.SelectedColor;
+ }
+ else
+ {
+ tabButton.Tab.SetActive(false);
+ tabButton.Button.sprite = this.NormalColor;
+ }
+ }
+ }
+
+ public void Close(bool canMove)
+ {
+ UnityEngine.Object.Destroy(base.gameObject);
+ }
+}
diff --git a/Client/Assembly-CSharp/DataCollectScreen.cs b/Client/Assembly-CSharp/DataCollectScreen.cs
new file mode 100644
index 0000000..7f89568
--- /dev/null
+++ b/Client/Assembly-CSharp/DataCollectScreen.cs
@@ -0,0 +1,56 @@
+using System;
+using System.Collections;
+using UnityEngine;
+
+public class DataCollectScreen : MonoBehaviour
+{
+ public static DataCollectScreen Instance;
+
+ public ToggleButtonBehaviour SendNameButton;
+
+ public ToggleButtonBehaviour SendTelemButton;
+
+ public AdDataCollectScreen AdPolicy;
+
+ private void Start()
+ {
+ DataCollectScreen.Instance = this;
+ this.UpdateButtons();
+ }
+
+ public IEnumerator Show()
+ {
+ if (!SaveManager.SendDataScreen)
+ {
+ base.gameObject.SetActive(true);
+ while (base.gameObject.activeSelf)
+ {
+ yield return null;
+ }
+ }
+ yield break;
+ }
+
+ public void Close()
+ {
+ SaveManager.SendDataScreen = true;
+ }
+
+ public void ToggleSendTelemetry()
+ {
+ SaveManager.SendTelemetry = !SaveManager.SendTelemetry;
+ this.UpdateButtons();
+ }
+
+ public void ToggleSendName()
+ {
+ SaveManager.SendName = !SaveManager.SendName;
+ this.UpdateButtons();
+ }
+
+ public void UpdateButtons()
+ {
+ this.SendNameButton.UpdateText(SaveManager.SendName);
+ this.SendTelemButton.UpdateText(SaveManager.SendTelemetry);
+ }
+}
diff --git a/Client/Assembly-CSharp/DeadBody.cs b/Client/Assembly-CSharp/DeadBody.cs
new file mode 100644
index 0000000..5cab24a
--- /dev/null
+++ b/Client/Assembly-CSharp/DeadBody.cs
@@ -0,0 +1,35 @@
+using System;
+using UnityEngine;
+
+public class DeadBody : MonoBehaviour
+{
+ public Vector2 TruePosition
+ {
+ get
+ {
+ return base.transform.position + this.myCollider.offset;
+ }
+ }
+
+ public bool Reported;
+
+ public short KillIdx;
+
+ public byte ParentId;
+
+ public Collider2D myCollider;
+
+ public void OnClick()
+ {
+ if (this.Reported)
+ {
+ return;
+ }
+ if (!PhysicsHelpers.AnythingBetween(PlayerControl.LocalPlayer.GetTruePosition(), this.TruePosition, Constants.ShipAndObjectsMask, false))
+ {
+ this.Reported = true;
+ GameData.PlayerInfo playerById = GameData.Instance.GetPlayerById(this.ParentId);
+ PlayerControl.LocalPlayer.CmdReportDeadBody(playerById);
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/DeathReason.cs b/Client/Assembly-CSharp/DeathReason.cs
new file mode 100644
index 0000000..f5d99e5
--- /dev/null
+++ b/Client/Assembly-CSharp/DeathReason.cs
@@ -0,0 +1,8 @@
+using System;
+
+public enum DeathReason
+{
+ Exile,
+ Kill,
+ Disconnect
+}
diff --git a/Client/Assembly-CSharp/DeconSystem.cs b/Client/Assembly-CSharp/DeconSystem.cs
new file mode 100644
index 0000000..0eb0b9d
--- /dev/null
+++ b/Client/Assembly-CSharp/DeconSystem.cs
@@ -0,0 +1,163 @@
+using System;
+using Hazel;
+using UnityEngine;
+
+public class DeconSystem : MonoBehaviour, ISystemType
+{
+ private const byte HeadUpCmd = 1;
+
+ private const byte HeadDownCmd = 2;
+
+ private const byte HeadUpInsideCmd = 3;
+
+ private const byte HeadDownInsideCmd = 4;
+
+ public ManualDoor UpperDoor;
+
+ public ManualDoor LowerDoor;
+
+ public float DoorOpenTime = 5f;
+
+ public float DeconTime = 5f;
+
+ private DeconSystem.States curState;
+
+ private float timer;
+
+ public TextRenderer FloorText;
+
+ [Flags]
+ private enum States : byte
+ {
+ Idle = 0,
+ Enter = 1,
+ Closed = 2,
+ Exit = 4,
+ HeadingUp = 8
+ }
+
+ public bool Detoriorate(float dt)
+ {
+ int num = Mathf.CeilToInt(this.timer);
+ this.timer = Mathf.Max(0f, this.timer - dt);
+ int num2 = Mathf.CeilToInt(this.timer);
+ if (num != num2)
+ {
+ if (num2 == 0)
+ {
+ if (this.curState.HasFlag(DeconSystem.States.Enter))
+ {
+ this.curState = ((this.curState & ~DeconSystem.States.Enter) | DeconSystem.States.Closed);
+ this.timer = this.DeconTime;
+ }
+ else if (this.curState.HasFlag(DeconSystem.States.Closed))
+ {
+ this.curState = ((this.curState & ~DeconSystem.States.Closed) | DeconSystem.States.Exit);
+ this.timer = this.DoorOpenTime;
+ }
+ else if (this.curState.HasFlag(DeconSystem.States.Exit))
+ {
+ this.curState = DeconSystem.States.Idle;
+ }
+ }
+ this.UpdateDoorsViaState();
+ return true;
+ }
+ return false;
+ }
+
+ public void OpenDoor(bool upper)
+ {
+ if (this.curState == DeconSystem.States.Idle)
+ {
+ ShipStatus.Instance.RpcRepairSystem(SystemTypes.Decontamination, upper ? 2 : 1);
+ }
+ }
+
+ public void OpenFromInside(bool upper)
+ {
+ if (this.curState == DeconSystem.States.Idle)
+ {
+ ShipStatus.Instance.RpcRepairSystem(SystemTypes.Decontamination, upper ? 3 : 4);
+ }
+ }
+
+ public void RepairDamage(PlayerControl player, byte amount)
+ {
+ if (this.curState != DeconSystem.States.Idle)
+ {
+ return;
+ }
+ switch (amount)
+ {
+ case 1:
+ this.curState = (DeconSystem.States.Enter | DeconSystem.States.HeadingUp);
+ this.timer = this.DoorOpenTime;
+ break;
+ case 2:
+ this.curState = DeconSystem.States.Enter;
+ this.timer = this.DoorOpenTime;
+ break;
+ case 3:
+ this.curState = (DeconSystem.States.Exit | DeconSystem.States.HeadingUp);
+ this.timer = this.DoorOpenTime;
+ break;
+ case 4:
+ this.curState = DeconSystem.States.Exit;
+ this.timer = this.DoorOpenTime;
+ break;
+ }
+ this.UpdateDoorsViaState();
+ }
+
+ public void Serialize(MessageWriter writer, bool initialState)
+ {
+ writer.Write((byte)Mathf.CeilToInt(this.timer));
+ writer.Write((byte)this.curState);
+ }
+
+ public void Deserialize(MessageReader reader, bool initialState)
+ {
+ this.timer = (float)reader.ReadByte();
+ this.curState = (DeconSystem.States)reader.ReadByte();
+ this.UpdateDoorsViaState();
+ }
+
+ private void UpdateDoorsViaState()
+ {
+ int num = Mathf.CeilToInt(this.timer);
+ if (num > 0)
+ {
+ this.FloorText.Text = string.Join("\n", new object[]
+ {
+ num,
+ num,
+ num,
+ num
+ });
+ }
+ else
+ {
+ this.FloorText.Text = string.Empty;
+ }
+ if (this.curState.HasFlag(DeconSystem.States.Enter))
+ {
+ bool flag = this.curState.HasFlag(DeconSystem.States.HeadingUp);
+ this.LowerDoor.SetDoorway(flag);
+ this.UpperDoor.SetDoorway(!flag);
+ return;
+ }
+ if (this.curState.HasFlag(DeconSystem.States.Closed) || this.curState == DeconSystem.States.Idle)
+ {
+ this.LowerDoor.SetDoorway(false);
+ this.UpperDoor.SetDoorway(false);
+ return;
+ }
+ if (this.curState.HasFlag(DeconSystem.States.Exit))
+ {
+ bool flag2 = this.curState.HasFlag(DeconSystem.States.HeadingUp);
+ this.LowerDoor.SetDoorway(!flag2);
+ this.UpperDoor.SetDoorway(flag2);
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/DefaultPool.cs b/Client/Assembly-CSharp/DefaultPool.cs
new file mode 100644
index 0000000..676c666
--- /dev/null
+++ b/Client/Assembly-CSharp/DefaultPool.cs
@@ -0,0 +1,82 @@
+using System;
+using UnityEngine;
+
+public class DefaultPool : IObjectPool
+{
+ public override int InUse
+ {
+ get
+ {
+ return 0;
+ }
+ }
+
+ public override int NotInUse
+ {
+ get
+ {
+ return 0;
+ }
+ }
+
+ public static bool InstanceExists
+ {
+ get
+ {
+ return DefaultPool._instance;
+ }
+ }
+
+ public static DefaultPool Instance
+ {
+ get
+ {
+ object @lock = DefaultPool._lock;
+ DefaultPool instance;
+ lock (@lock)
+ {
+ if (DefaultPool._instance == null)
+ {
+ DefaultPool._instance = UnityEngine.Object.FindObjectOfType<DefaultPool>();
+ if (UnityEngine.Object.FindObjectsOfType<DefaultPool>().Length > 1)
+ {
+ Debug.LogError("[Singleton] Something went really wrong - there should never be more than 1 singleton! Reopening the scene might fix it.");
+ return DefaultPool._instance;
+ }
+ if (DefaultPool._instance == null)
+ {
+ GameObject gameObject = new GameObject();
+ DefaultPool._instance = gameObject.AddComponent<DefaultPool>();
+ gameObject.name = "(singleton) DefaultPool";
+ }
+ }
+ instance = DefaultPool._instance;
+ }
+ return instance;
+ }
+ }
+
+ private static DefaultPool _instance;
+
+ private static object _lock = new object();
+
+ public void OnDestroy()
+ {
+ object @lock = DefaultPool._lock;
+ lock (@lock)
+ {
+ DefaultPool._instance = null;
+ }
+ }
+
+ public override T Get<T>()
+ {
+ throw new NotImplementedException();
+ }
+
+ public override void Reclaim(PoolableBehavior obj)
+ {
+ Debug.Log("Default Pool: Destroying this thing.");
+ UnityEngine.Object.Destroy(obj.gameObject);
+ }
+}
diff --git a/Client/Assembly-CSharp/DemoKeyboardStick.cs b/Client/Assembly-CSharp/DemoKeyboardStick.cs
new file mode 100644
index 0000000..bacd4d9
--- /dev/null
+++ b/Client/Assembly-CSharp/DemoKeyboardStick.cs
@@ -0,0 +1,25 @@
+using System;
+using UnityEngine;
+
+public class DemoKeyboardStick : VirtualJoystick
+{
+ public SpriteRenderer UpKey;
+
+ public SpriteRenderer DownKey;
+
+ public SpriteRenderer LeftKey;
+
+ public SpriteRenderer RightKey;
+
+ protected override void FixedUpdate()
+ {
+ }
+
+ public override void UpdateJoystick(FingerBehaviour finger, Vector2 velocity, bool syncFinger)
+ {
+ this.UpKey.enabled = (velocity.y > 0.1f);
+ this.DownKey.enabled = (velocity.y < -0.1f);
+ this.RightKey.enabled = (velocity.x > 0.1f);
+ this.LeftKey.enabled = (velocity.x < -0.1f);
+ }
+}
diff --git a/Client/Assembly-CSharp/DestroyableSingleton.cs b/Client/Assembly-CSharp/DestroyableSingleton.cs
new file mode 100644
index 0000000..bcd8319
--- /dev/null
+++ b/Client/Assembly-CSharp/DestroyableSingleton.cs
@@ -0,0 +1,58 @@
+using System;
+using UnityEngine;
+
+public class DestroyableSingleton<T> : MonoBehaviour where T : MonoBehaviour
+{
+ public static bool InstanceExists
+ {
+ get
+ {
+ return DestroyableSingleton<T>._instance;
+ }
+ }
+
+ public static T Instance
+ {
+ get
+ {
+ if (!DestroyableSingleton<T>._instance)
+ {
+ DestroyableSingleton<T>._instance = UnityEngine.Object.FindObjectOfType<T>();
+ if (!DestroyableSingleton<T>._instance)
+ {
+ DestroyableSingleton<T>._instance = new GameObject().AddComponent<T>();
+ }
+ }
+ return DestroyableSingleton<T>._instance;
+ }
+ }
+
+ private static T _instance;
+
+ public bool DontDestroy;
+
+ public virtual void Awake()
+ {
+ if (!DestroyableSingleton<T>._instance)
+ {
+ DestroyableSingleton<T>._instance = (this as T);
+ if (this.DontDestroy)
+ {
+ UnityEngine.Object.DontDestroyOnLoad(base.gameObject);
+ return;
+ }
+ }
+ else if (DestroyableSingleton<T>._instance != this)
+ {
+ UnityEngine.Object.Destroy(base.gameObject);
+ }
+ }
+
+ public virtual void OnDestroy()
+ {
+ if (!this.DontDestroy)
+ {
+ DestroyableSingleton<T>._instance = default(T);
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/DialBehaviour.cs b/Client/Assembly-CSharp/DialBehaviour.cs
new file mode 100644
index 0000000..d306e24
--- /dev/null
+++ b/Client/Assembly-CSharp/DialBehaviour.cs
@@ -0,0 +1,46 @@
+using System;
+using UnityEngine;
+
+public class DialBehaviour : MonoBehaviour
+{
+ public FloatRange DialRange;
+
+ public Collider2D collider;
+
+ public Controller myController = new Controller();
+
+ public float Value;
+
+ public bool Engaged;
+
+ public Transform DialTrans;
+
+ public Transform DialShadTrans;
+
+ public void Update()
+ {
+ this.Engaged = false;
+ this.myController.Update();
+ DragState dragState = this.myController.CheckDrag(this.collider, false);
+ if (dragState == DragState.Dragging)
+ {
+ Vector2 vector = this.myController.DragPosition - base.transform.position;
+ float num = Vector2.up.AngleSigned(vector);
+ if (num < -180f)
+ {
+ num += 360f;
+ }
+ num = this.DialRange.Clamp(num);
+ this.SetValue(num);
+ this.Engaged = true;
+ }
+ }
+
+ public void SetValue(float angle)
+ {
+ this.Value = angle;
+ Vector3 localEulerAngles = new Vector3(0f, 0f, angle);
+ this.DialTrans.localEulerAngles = localEulerAngles;
+ this.DialShadTrans.localEulerAngles = localEulerAngles;
+ }
+}
diff --git a/Client/Assembly-CSharp/DialogueBox.cs b/Client/Assembly-CSharp/DialogueBox.cs
new file mode 100644
index 0000000..63fe612
--- /dev/null
+++ b/Client/Assembly-CSharp/DialogueBox.cs
@@ -0,0 +1,27 @@
+using System;
+using UnityEngine;
+
+public class DialogueBox : MonoBehaviour
+{
+ public TextRenderer target;
+
+ public void Show(string dialogue)
+ {
+ this.target.Text = dialogue;
+ if (Minigame.Instance)
+ {
+ Minigame.Instance.Close();
+ Minigame.Instance.Close();
+ }
+ PlayerControl.LocalPlayer.moveable = false;
+ PlayerControl.LocalPlayer.NetTransform.Halt();
+ base.gameObject.SetActive(true);
+ }
+
+ public void Hide()
+ {
+ base.gameObject.SetActive(false);
+ PlayerControl.LocalPlayer.moveable = true;
+ Camera.main.GetComponent<FollowerCamera>().Locked = false;
+ }
+}
diff --git a/Client/Assembly-CSharp/DisconnectPopup.cs b/Client/Assembly-CSharp/DisconnectPopup.cs
new file mode 100644
index 0000000..6feeed5
--- /dev/null
+++ b/Client/Assembly-CSharp/DisconnectPopup.cs
@@ -0,0 +1,112 @@
+using System;
+using InnerNet;
+
+public class DisconnectPopup : DestroyableSingleton<DisconnectPopup>
+{
+ public TextRenderer TextArea;
+
+ public void Start()
+ {
+ if (DestroyableSingleton<DisconnectPopup>.Instance == this)
+ {
+ this.Show();
+ }
+ }
+
+ public void Show()
+ {
+ base.gameObject.SetActive(true);
+ this.DoShow();
+ }
+
+ private void DoShow()
+ {
+ if (DestroyableSingleton<WaitForHostPopup>.InstanceExists)
+ {
+ DestroyableSingleton<WaitForHostPopup>.Instance.Hide();
+ }
+ if (!AmongUsClient.Instance)
+ {
+ base.gameObject.SetActive(false);
+ return;
+ }
+ string text = InnerNetClient.IntToGameName(AmongUsClient.Instance.GameId);
+ string str = (text != null) ? (" from " + text) : " from the room";
+ DisconnectReasons lastDisconnectReason = AmongUsClient.Instance.LastDisconnectReason;
+ switch (lastDisconnectReason)
+ {
+ case DisconnectReasons.ExitGame:
+ case DisconnectReasons.Destroy:
+ base.gameObject.SetActive(false);
+ break;
+ case DisconnectReasons.GameFull:
+ this.TextArea.Text = "The game you tried to join is full.\r\n\r\nCheck with the host to see if you can join next round.";
+ return;
+ case DisconnectReasons.GameStarted:
+ this.TextArea.Text = "The game you tried to join already started.\r\n\r\nCheck with the host to see if you can join next round.";
+ return;
+ case DisconnectReasons.GameNotFound:
+ case DisconnectReasons.IncorrectGame:
+ this.TextArea.Text = "Could not find the game you're looking for.";
+ return;
+ case (DisconnectReasons)4:
+ case (DisconnectReasons)9:
+ case (DisconnectReasons)10:
+ case (DisconnectReasons)11:
+ case (DisconnectReasons)12:
+ case (DisconnectReasons)13:
+ case (DisconnectReasons)14:
+ case (DisconnectReasons)15:
+ break;
+ case DisconnectReasons.IncorrectVersion:
+ this.TextArea.Text = "You are running an older version of the game.\r\n\r\nPlease update to play with others.";
+ return;
+ case DisconnectReasons.Banned:
+ this.TextArea.Text = "You were banned" + str + ".\r\n\r\nYou cannot rejoin that room.";
+ return;
+ case DisconnectReasons.Kicked:
+ this.TextArea.Text = "You were kicked" + str + ".\r\n\r\nYou can rejoin if the room hasn't started.";
+ return;
+ case DisconnectReasons.Custom:
+ this.TextArea.Text = (AmongUsClient.Instance.LastCustomDisconnect ?? "An unknown error disconnected you from the server.");
+ return;
+ case DisconnectReasons.Error:
+ if (AmongUsClient.Instance.GameMode == GameModes.OnlineGame)
+ {
+ this.TextArea.Text = "You disconnected from the server.\r\nIf this happens often, check your network strength.\r\nThis may also be a server issue.";
+ return;
+ }
+ this.TextArea.Text = "You disconnected from the host.\r\n\r\nIf this happens often, check your WiFi strength.";
+ return;
+ case DisconnectReasons.ServerRequest:
+ this.TextArea.Text = "The server stopped this game. Possibly due to inactivity.";
+ return;
+ case DisconnectReasons.ServerFull:
+ this.TextArea.Text = "The Among Us servers are overloaded.\r\n\r\nSorry! Please try again later!";
+ return;
+ default:
+ if (lastDisconnectReason == DisconnectReasons.IntentionalLeaving)
+ {
+ this.TextArea.Text = string.Format("You may not join another game for another {0} minutes after intentionally disconnecting.", StatsManager.Instance.BanMinutesLeft);
+ return;
+ }
+ if (lastDisconnectReason != DisconnectReasons.FocusLost)
+ {
+ return;
+ }
+ this.TextArea.Text = "You were disconnected because Among Us was suspended by another app.";
+ return;
+ }
+ }
+
+ public void ShowCustom(string message)
+ {
+ base.gameObject.SetActive(true);
+ this.TextArea.Text = message;
+ }
+
+ public void Close()
+ {
+ base.gameObject.SetActive(false);
+ }
+}
diff --git a/Client/Assembly-CSharp/DiscordManager.cs b/Client/Assembly-CSharp/DiscordManager.cs
new file mode 100644
index 0000000..0ee1ea6
--- /dev/null
+++ b/Client/Assembly-CSharp/DiscordManager.cs
@@ -0,0 +1,207 @@
+using System;
+using System.Collections;
+using InnerNet;
+using UnityEngine;
+using UnityEngine.SceneManagement;
+
+public class DiscordManager : DestroyableSingleton<DiscordManager>
+{
+ private DiscordRpc.RichPresence presence = new DiscordRpc.RichPresence();
+
+ public DiscordRpc.DiscordUser joinRequest;
+
+ private DateTime? StartTime;
+
+ private static readonly DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
+
+ public void Start()
+ {
+ if (DestroyableSingleton<DiscordManager>.Instance == this)
+ {
+ DiscordRpc.EventHandlers eventHandlers = default(DiscordRpc.EventHandlers);
+ eventHandlers.errorCallback = (DiscordRpc.ErrorCallback)Delegate.Combine(eventHandlers.errorCallback, new DiscordRpc.ErrorCallback(this.HandleError));
+ eventHandlers.disconnectedCallback = (DiscordRpc.DisconnectedCallback)Delegate.Combine(eventHandlers.disconnectedCallback, new DiscordRpc.DisconnectedCallback(this.HandleError));
+ eventHandlers.joinCallback = (DiscordRpc.JoinCallback)Delegate.Combine(eventHandlers.joinCallback, new DiscordRpc.JoinCallback(this.HandleJoinRequest));
+ eventHandlers.requestCallback = (DiscordRpc.RequestCallback)Delegate.Combine(eventHandlers.requestCallback, new DiscordRpc.RequestCallback(this.HandleAutoJoin));
+ DiscordRpc.Initialize("477175586805252107", ref eventHandlers, true, null);
+ this.SetInMenus();
+ SceneManager.sceneLoaded += delegate(Scene scene, LoadSceneMode mode)
+ {
+ this.OnSceneChange(scene.name);
+ };
+ }
+ }
+
+ private void HandleError(int errorCode, string message)
+ {
+ Debug.LogError(message ?? string.Format("No message: {0}", errorCode));
+ }
+
+ private void OnSceneChange(string name)
+ {
+ if (name == "MatchMaking" || name == "MMOnline" || name == "MainMenu")
+ {
+ this.SetInMenus();
+ }
+ }
+
+ public void FixedUpdate()
+ {
+ DiscordRpc.RunCallbacks();
+ }
+
+ public void SetInMenus()
+ {
+ this.ClearPresence();
+ this.StartTime = null;
+ this.presence.state = "In Menus";
+ this.presence.largeImageKey = "icon";
+ DiscordRpc.UpdatePresence(this.presence);
+ }
+
+ public void SetPlayingGame()
+ {
+ if (this.StartTime == null)
+ {
+ this.StartTime = new DateTime?(DateTime.UtcNow);
+ }
+ this.presence.state = "In Game";
+ this.presence.details = "Playing";
+ this.presence.largeImageKey = "icon";
+ this.presence.startTimestamp = DiscordManager.ToUnixTime(this.StartTime.Value);
+ DiscordRpc.UpdatePresence(this.presence);
+ }
+
+ public void SetHowToPlay()
+ {
+ this.ClearPresence();
+ this.presence.state = "In Freeplay";
+ this.presence.largeImageKey = "icon";
+ DiscordRpc.UpdatePresence(this.presence);
+ }
+
+ public void SetInLobbyClient()
+ {
+ if (this.StartTime == null)
+ {
+ this.StartTime = new DateTime?(DateTime.UtcNow);
+ }
+ this.ClearPresence();
+ this.presence.state = "In Lobby";
+ this.presence.largeImageKey = "icon";
+ this.presence.startTimestamp = DiscordManager.ToUnixTime(this.StartTime.Value);
+ DiscordRpc.UpdatePresence(this.presence);
+ }
+
+ private void ClearPresence()
+ {
+ this.presence.startTimestamp = 0L;
+ this.presence.details = null;
+ this.presence.partyId = null;
+ this.presence.matchSecret = null;
+ this.presence.joinSecret = null;
+ this.presence.partySize = 0;
+ this.presence.partyMax = 0;
+ }
+
+ public void SetInLobbyHost(int numPlayers, int gameId)
+ {
+ if (this.StartTime == null)
+ {
+ this.StartTime = new DateTime?(DateTime.UtcNow);
+ }
+ string text = InnerNetClient.IntToGameName(gameId);
+ this.presence.state = "In Lobby";
+ this.presence.details = "Hosting a game";
+ this.presence.partySize = numPlayers;
+ this.presence.partyMax = 10;
+ this.presence.smallImageKey = "icon";
+ this.presence.largeImageText = "Ask to play!";
+ this.presence.joinSecret = "join" + text;
+ this.presence.matchSecret = "match" + text;
+ this.presence.partyId = text;
+ DiscordRpc.UpdatePresence(this.presence);
+ }
+
+ private void HandleAutoJoin(ref DiscordRpc.DiscordUser requestUser)
+ {
+ Debug.Log("Discord: request from " + requestUser.username);
+ if (AmongUsClient.Instance.IsGameStarted)
+ {
+ this.RequestRespondNo();
+ return;
+ }
+ this.RequestRespondYes();
+ }
+
+ private void HandleJoinRequest(string joinSecret)
+ {
+ if (!joinSecret.StartsWith("join"))
+ {
+ Debug.LogWarning("Invalid join secret: " + joinSecret);
+ return;
+ }
+ if (!AmongUsClient.Instance)
+ {
+ Debug.LogWarning("Missing AmongUsClient");
+ return;
+ }
+ if (!DestroyableSingleton<DiscordManager>.InstanceExists)
+ {
+ Debug.LogWarning("Missing DiscordManager");
+ return;
+ }
+ if (AmongUsClient.Instance.mode != MatchMakerModes.None)
+ {
+ Debug.LogWarning("Already connected");
+ return;
+ }
+ AmongUsClient.Instance.GameMode = GameModes.OnlineGame;
+ AmongUsClient.Instance.GameId = InnerNetClient.GameNameToInt(joinSecret.Substring(4));
+ AmongUsClient.Instance.SetEndpoint(DestroyableSingleton<ServerManager>.Instance.OnlineNetAddress, 22023);
+ AmongUsClient.Instance.MainMenuScene = "MMOnline";
+ AmongUsClient.Instance.OnlineScene = "OnlineGame";
+ DestroyableSingleton<DiscordManager>.Instance.StopAllCoroutines();
+ DestroyableSingleton<DiscordManager>.Instance.StartCoroutine(DestroyableSingleton<DiscordManager>.Instance.CoJoinGame());
+ }
+
+ public IEnumerator CoJoinGame()
+ {
+ while (DataCollectScreen.Instance && DataCollectScreen.Instance.isActiveAndEnabled)
+ {
+ yield return null;
+ }
+ AmongUsClient.Instance.Connect(MatchMakerModes.Client);
+ yield return AmongUsClient.Instance.WaitForConnectionOrFail();
+ if (AmongUsClient.Instance.ClientId < 0)
+ {
+ SceneManager.LoadScene("MMOnline");
+ }
+ yield break;
+ }
+
+ public void RequestRespondYes()
+ {
+ DiscordRpc.Respond(this.joinRequest.userId, DiscordRpc.Reply.Yes);
+ }
+
+ public void RequestRespondNo()
+ {
+ Debug.Log("Discord: responding no to Ask to Join request");
+ DiscordRpc.Respond(this.joinRequest.userId, DiscordRpc.Reply.No);
+ }
+
+ public override void OnDestroy()
+ {
+ base.OnDestroy();
+ if (DestroyableSingleton<DiscordManager>.Instance == this)
+ {
+ DiscordRpc.Shutdown();
+ }
+ }
+
+ private static long ToUnixTime(DateTime time)
+ {
+ return (long)(time - DiscordManager.epoch).TotalSeconds;
+ }
+}
diff --git a/Client/Assembly-CSharp/DiscoveryState.cs b/Client/Assembly-CSharp/DiscoveryState.cs
new file mode 100644
index 0000000..4da2cfc
--- /dev/null
+++ b/Client/Assembly-CSharp/DiscoveryState.cs
@@ -0,0 +1,7 @@
+using System;
+
+public enum DiscoveryState
+{
+ Off,
+ Broadcast
+}
diff --git a/Client/Assembly-CSharp/DiscussBehaviour.cs b/Client/Assembly-CSharp/DiscussBehaviour.cs
new file mode 100644
index 0000000..9a99207
--- /dev/null
+++ b/Client/Assembly-CSharp/DiscussBehaviour.cs
@@ -0,0 +1,65 @@
+using System;
+using System.Collections;
+using UnityEngine;
+
+public class DiscussBehaviour : MonoBehaviour
+{
+ public SpriteRenderer LeftPlayer;
+
+ public SpriteRenderer RightPlayer;
+
+ public SpriteRenderer Text;
+
+ public FloatRange RotateRange = new FloatRange(-5f, 5f);
+
+ public Vector2Range TextTarget;
+
+ public AnimationCurve TextEasing;
+
+ public float Delay = 0.1f;
+
+ public float TextDuration = 0.5f;
+
+ public float HoldDuration = 2f;
+
+ private Vector3 vec;
+
+ public IEnumerator PlayAnimation()
+ {
+ this.Text.transform.localPosition = this.TextTarget.min;
+ yield return this.AnimateText();
+ yield return ShhhBehaviour.WaitWithInterrupt(this.HoldDuration);
+ yield break;
+ }
+
+ public void Update()
+ {
+ this.vec.Set(0f, 0f, this.RotateRange.Lerp(Mathf.PerlinNoise(1f, Time.time * 8f)));
+ this.LeftPlayer.transform.eulerAngles = this.vec;
+ this.vec.Set(0f, 0f, this.RotateRange.Lerp(Mathf.PerlinNoise(2f, Time.time * 8f)));
+ this.RightPlayer.transform.eulerAngles = this.vec;
+ }
+
+ private IEnumerator AnimateText()
+ {
+ for (float t = 0f; t < this.Delay; t += Time.deltaTime)
+ {
+ yield return null;
+ }
+ Vector3 vec = default(Vector3);
+ for (float t = 0f; t < this.TextDuration; t += Time.deltaTime)
+ {
+ float time = t / this.TextDuration;
+ this.UpdateText(ref vec, this.TextEasing.Evaluate(time));
+ yield return null;
+ }
+ this.UpdateText(ref vec, 1f);
+ yield break;
+ }
+
+ private void UpdateText(ref Vector3 vec, float p)
+ {
+ this.TextTarget.LerpUnclamped(ref vec, p, -7f);
+ this.Text.transform.localPosition = vec;
+ }
+}
diff --git a/Client/Assembly-CSharp/DivertPowerMetagame.cs b/Client/Assembly-CSharp/DivertPowerMetagame.cs
new file mode 100644
index 0000000..1be1bf3
--- /dev/null
+++ b/Client/Assembly-CSharp/DivertPowerMetagame.cs
@@ -0,0 +1,25 @@
+using System;
+using UnityEngine;
+
+public class DivertPowerMetagame : Minigame
+{
+ public Minigame DistributePrefab;
+
+ public Minigame ReceivePrefab;
+
+ public override void Begin(PlayerTask task)
+ {
+ base.Begin(task);
+ Minigame minigame;
+ if (this.MyNormTask.taskStep == 0)
+ {
+ minigame = UnityEngine.Object.Instantiate<Minigame>(this.DistributePrefab, base.transform.parent);
+ }
+ else
+ {
+ minigame = UnityEngine.Object.Instantiate<Minigame>(this.ReceivePrefab, base.transform.parent);
+ }
+ minigame.Begin(task);
+ UnityEngine.Object.Destroy(base.gameObject);
+ }
+}
diff --git a/Client/Assembly-CSharp/DivertPowerMinigame.cs b/Client/Assembly-CSharp/DivertPowerMinigame.cs
new file mode 100644
index 0000000..64aa786
--- /dev/null
+++ b/Client/Assembly-CSharp/DivertPowerMinigame.cs
@@ -0,0 +1,91 @@
+using System;
+using UnityEngine;
+
+public class DivertPowerMinigame : Minigame
+{
+ public SystemTypes[] SliderOrder = new SystemTypes[]
+ {
+ SystemTypes.LowerEngine,
+ SystemTypes.UpperEngine,
+ SystemTypes.Weapons,
+ SystemTypes.Shields,
+ SystemTypes.Nav,
+ SystemTypes.Comms,
+ SystemTypes.LifeSupp,
+ SystemTypes.Security
+ };
+
+ public Collider2D[] Sliders;
+
+ public LineRenderer[] Wires;
+
+ public VerticalGauge[] Gauges;
+
+ private int sliderId;
+
+ public FloatRange SliderY = new FloatRange(-1f, 1f);
+
+ private Controller myController = new Controller();
+
+ public override void Begin(PlayerTask task)
+ {
+ base.Begin(task);
+ DivertPowerTask powerTask = (DivertPowerTask)task;
+ this.sliderId = this.SliderOrder.IndexOf((SystemTypes t) => t == powerTask.TargetSystem);
+ for (int i = 0; i < this.Sliders.Length; i++)
+ {
+ if (i != this.sliderId)
+ {
+ this.Sliders[i].GetComponent<SpriteRenderer>().color = new Color(0.5f, 0.5f, 0.5f);
+ }
+ }
+ }
+
+ public void FixedUpdate()
+ {
+ this.myController.Update();
+ float num = 0f;
+ for (int i = 0; i < this.Sliders.Length; i++)
+ {
+ num += this.SliderY.ReverseLerp(this.Sliders[i].transform.localPosition.y) / (float)this.Sliders.Length;
+ }
+ for (int j = 0; j < this.Sliders.Length; j++)
+ {
+ float num2 = this.SliderY.ReverseLerp(this.Sliders[j].transform.localPosition.y);
+ float num3 = num2 / num / 1.6f;
+ this.Gauges[j].value = num3 + (Mathf.PerlinNoise((float)j, Time.time * 51f) - 0.5f) * 0.04f;
+ Color value = Color.Lerp(Color.gray, Color.yellow, num2 * num2);
+ value.a = (float)((num3 < 0.1f) ? 0 : 1);
+ Vector2 textureOffset = this.Wires[j].material.GetTextureOffset("_MainTex");
+ textureOffset.x -= Time.fixedDeltaTime * 3f * Mathf.Lerp(0.1f, 2f, num3);
+ this.Wires[j].material.SetTextureOffset("_MainTex", textureOffset);
+ this.Wires[j].material.SetColor("_Color", value);
+ }
+ if (this.sliderId < 0)
+ {
+ return;
+ }
+ Collider2D collider2D = this.Sliders[this.sliderId];
+ Vector2 vector = collider2D.transform.localPosition;
+ DragState dragState = this.myController.CheckDrag(collider2D, false);
+ if (dragState == DragState.Dragging)
+ {
+ Vector2 vector2 = this.myController.DragPosition - collider2D.transform.parent.position;
+ vector2.y = this.SliderY.Clamp(vector2.y);
+ vector.y = vector2.y;
+ collider2D.transform.localPosition = vector;
+ return;
+ }
+ if (dragState != DragState.Released)
+ {
+ return;
+ }
+ if (this.SliderY.max - vector.y < 0.05f)
+ {
+ this.MyNormTask.NextStep();
+ base.StartCoroutine(base.CoStartClose(0.75f));
+ this.sliderId = -1;
+ collider2D.GetComponent<SpriteRenderer>().color = new Color(0.5f, 0.5f, 0.5f);
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/DivertPowerTask.cs b/Client/Assembly-CSharp/DivertPowerTask.cs
new file mode 100644
index 0000000..f970ae3
--- /dev/null
+++ b/Client/Assembly-CSharp/DivertPowerTask.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Linq;
+using System.Text;
+
+public class DivertPowerTask : NormalPlayerTask
+{
+ public SystemTypes TargetSystem;
+
+ public override bool ValidConsole(global::Console console)
+ {
+ return (console.Room == this.TargetSystem && console.ValidTasks.Any((TaskSet set) => this.TaskType == set.taskType && set.taskStep.Contains(this.taskStep))) || (this.taskStep == 0 && console.TaskTypes.Contains(this.TaskType));
+ }
+
+ public override void AppendTaskText(StringBuilder sb)
+ {
+ if (this.taskStep > 0)
+ {
+ if (this.IsComplete)
+ {
+ sb.Append("[00DD00FF]");
+ }
+ else
+ {
+ sb.Append("[FFFF00FF]");
+ }
+ }
+ if (this.taskStep == 0)
+ {
+ sb.Append(DestroyableSingleton<TranslationController>.Instance.GetString(this.StartAt));
+ sb.Append(": ");
+ sb.Append(DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.DivertPowerTo, Array.Empty<object>()));
+ sb.Append(" ");
+ sb.Append(DestroyableSingleton<TranslationController>.Instance.GetString(this.TargetSystem));
+ }
+ else
+ {
+ sb.Append(DestroyableSingleton<TranslationController>.Instance.GetString(this.TargetSystem));
+ sb.Append(": ");
+ sb.Append(DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.AcceptDivertedPower, Array.Empty<object>()));
+ }
+ sb.Append(" (");
+ sb.Append(this.taskStep);
+ sb.Append("/");
+ sb.Append(this.MaxStep);
+ sb.AppendLine(")");
+ if (this.taskStep > 0)
+ {
+ sb.Append("[]");
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/DoorsSystemType.cs b/Client/Assembly-CSharp/DoorsSystemType.cs
new file mode 100644
index 0000000..e642713
--- /dev/null
+++ b/Client/Assembly-CSharp/DoorsSystemType.cs
@@ -0,0 +1,119 @@
+using System;
+using System.Linq;
+using Hazel;
+
+//c 管理场景中的门,同步门的开启状态
+public class DoorsSystemType : ISystemType, IActivatable
+{
+ public bool IsActive
+ {
+ get
+ {
+ return this.doors.Any((AutoOpenDoor b) => !b.Open);
+ }
+ }
+
+ private AutoOpenDoor[] doors; // 场景所有的门
+
+ private uint dirtyBits;
+
+ public void SetDoors(AutoOpenDoor[] doors)
+ {
+ this.doors = doors;
+ }
+
+ public bool Detoriorate(float deltaTime)
+ {
+ if (this.doors == null)
+ {
+ return false;
+ }
+ for (int i = 0; i < this.doors.Length; i++)
+ {
+ if (this.doors[i].DoUpdate(deltaTime))
+ {
+ this.dirtyBits |= 1U << i;
+ }
+ }
+ return this.dirtyBits > 0U;
+ }
+
+ public void RepairDamage(PlayerControl player, byte amount)
+ {
+ }
+
+ //c 同步场景中所有门的开启状态
+
+ public void Serialize(MessageWriter writer, bool initialState)
+ {
+ if (initialState)
+ {
+ for (int i = 0; i < this.doors.Length; i++)
+ {
+ this.doors[i].Serialize(writer);
+ }
+ return;
+ }
+ writer.WritePacked(this.dirtyBits);
+ for (int j = 0; j < this.doors.Length; j++)
+ {
+ if ((this.dirtyBits & 1U << j) != 0U)
+ {
+ this.doors[j].Serialize(writer);
+ }
+ }
+ this.dirtyBits = 0U;
+ }
+
+ public void Deserialize(MessageReader reader, bool initialState)
+ {
+ if (initialState)
+ {
+ for (int i = 0; i < this.doors.Length; i++)
+ {
+ this.doors[i].Deserialize(reader);
+ }
+ return;
+ }
+ uint num = reader.ReadPackedUInt32();
+ for (int j = 0; j < this.doors.Length; j++)
+ {
+ if ((num & 1U << j) != 0U)
+ {
+ this.doors[j].Deserialize(reader);
+ }
+ }
+ }
+
+ public void SetDoor(AutoOpenDoor door, bool open)
+ {
+ door.SetDoorway(open);
+ this.dirtyBits |= 1U << this.doors.IndexOf(door);
+ }
+
+ public void CloseDoorsOfType(SystemTypes room)
+ {
+ for (int i = 0; i < this.doors.Length; i++)
+ {
+ AutoOpenDoor autoOpenDoor = this.doors[i];
+ if (autoOpenDoor.Room == room)
+ {
+ autoOpenDoor.SetDoorway(false);
+ this.dirtyBits |= 1U << i;
+ }
+ }
+ }
+
+ public float GetTimer(SystemTypes room)
+ {
+ for (int i = 0; i < this.doors.Length; i++)
+ {
+ AutoOpenDoor autoOpenDoor = this.doors[i];
+ if (autoOpenDoor.Room == room)
+ {
+ return autoOpenDoor.CooldownTimer;
+ }
+ }
+ return 0f;
+ }
+}
diff --git a/Client/Assembly-CSharp/DotAligner.cs b/Client/Assembly-CSharp/DotAligner.cs
new file mode 100644
index 0000000..149f4c8
--- /dev/null
+++ b/Client/Assembly-CSharp/DotAligner.cs
@@ -0,0 +1,43 @@
+using System;
+using UnityEngine;
+
+public class DotAligner : MonoBehaviour
+{
+ public float Width = 2f;
+
+ public bool Even;
+
+ public void Start()
+ {
+ int num = 0;
+ for (int i = 0; i < base.transform.childCount; i++)
+ {
+ if (base.transform.GetChild(i).gameObject.activeSelf)
+ {
+ num++;
+ }
+ }
+ float num2;
+ float num3;
+ if (this.Even)
+ {
+ num2 = -this.Width * (float)(num - 1) / 2f;
+ num3 = this.Width;
+ }
+ else
+ {
+ num2 = -this.Width / 2f;
+ num3 = this.Width / (float)(num - 1);
+ }
+ int num4 = 0;
+ for (int j = 0; j < base.transform.childCount; j++)
+ {
+ Transform child = base.transform.GetChild(j);
+ if (child.gameObject.activeSelf)
+ {
+ child.transform.localPosition = new Vector3(num2 + (float)num4 * num3, 0f, 0f);
+ num4++;
+ }
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/DragState.cs b/Client/Assembly-CSharp/DragState.cs
new file mode 100644
index 0000000..6b99f71
--- /dev/null
+++ b/Client/Assembly-CSharp/DragState.cs
@@ -0,0 +1,9 @@
+using System;
+
+public enum DragState
+{
+ NoTouch,
+ TouchStart,
+ Dragging,
+ Released
+}
diff --git a/Client/Assembly-CSharp/DummyBehaviour.cs b/Client/Assembly-CSharp/DummyBehaviour.cs
new file mode 100644
index 0000000..58beb6f
--- /dev/null
+++ b/Client/Assembly-CSharp/DummyBehaviour.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Collections;
+using UnityEngine;
+
+public class DummyBehaviour : MonoBehaviour
+{
+ private PlayerControl myPlayer;
+
+ private FloatRange voteTime = new FloatRange(3f, 8f);
+
+ private bool voted;
+
+ public void Start()
+ {
+ this.myPlayer = base.GetComponent<PlayerControl>();
+ }
+
+ public void Update()
+ {
+ if (this.myPlayer.Data.IsDead)
+ {
+ return;
+ }
+ if (MeetingHud.Instance)
+ {
+ if (!this.voted)
+ {
+ this.voted = true;
+ base.StartCoroutine(this.DoVote());
+ return;
+ }
+ }
+ else
+ {
+ this.voted = false;
+ }
+ }
+
+ private IEnumerator DoVote()
+ {
+ yield return new WaitForSeconds(this.voteTime.Next());
+ sbyte suspectIdx = -1;
+ int num = 0;
+ while (num < 100 && num != 99)
+ {
+ int num2 = IntRange.Next(-1, GameData.Instance.PlayerCount);
+ if (num2 < 0)
+ {
+ suspectIdx = (sbyte)num2;
+ break;
+ }
+ GameData.PlayerInfo playerInfo = GameData.Instance.AllPlayers[num2];
+ if (!playerInfo.IsDead)
+ {
+ suspectIdx = (sbyte)playerInfo.PlayerId;
+ break;
+ }
+ num++;
+ }
+ MeetingHud.Instance.CmdCastVote(this.myPlayer.PlayerId, suspectIdx);
+ yield break;
+ }
+}
diff --git a/Client/Assembly-CSharp/DummyConsole.cs b/Client/Assembly-CSharp/DummyConsole.cs
new file mode 100644
index 0000000..cb053ae
--- /dev/null
+++ b/Client/Assembly-CSharp/DummyConsole.cs
@@ -0,0 +1,57 @@
+using System;
+using UnityEngine;
+
+public class DummyConsole : MonoBehaviour
+{
+ public int ConsoleId;
+
+ public PlayerAnimator[] Players;
+
+ public float UseDistance;
+
+ [HideInInspector]
+ private SpriteRenderer rend;
+
+ public void Start()
+ {
+ this.rend = base.GetComponent<SpriteRenderer>();
+ }
+
+ public void FixedUpdate()
+ {
+ this.rend.material.SetColor("_OutlineColor", Color.yellow);
+ float num = float.MaxValue;
+ for (int i = 0; i < this.Players.Length; i++)
+ {
+ PlayerAnimator playerAnimator = this.Players[i];
+ Vector2 vector = base.transform.position - playerAnimator.transform.position;
+ vector.y += 0.3636f;
+ float magnitude = vector.magnitude;
+ if (magnitude < num)
+ {
+ num = magnitude;
+ }
+ if (magnitude < this.UseDistance)
+ {
+ playerAnimator.NearbyConsoles |= 1 << this.ConsoleId;
+ }
+ else
+ {
+ playerAnimator.NearbyConsoles &= ~(1 << this.ConsoleId);
+ }
+ }
+ if (num >= this.UseDistance * 2f)
+ {
+ this.rend.material.SetFloat("_Outline", 0f);
+ this.rend.material.SetColor("_AddColor", Color.clear);
+ return;
+ }
+ this.rend.material.SetFloat("_Outline", 1f);
+ if (num < this.UseDistance)
+ {
+ this.rend.material.SetColor("_AddColor", Color.yellow);
+ return;
+ }
+ this.rend.material.SetColor("_AddColor", Color.clear);
+ }
+}
diff --git a/Client/Assembly-CSharp/DynamicSound.cs b/Client/Assembly-CSharp/DynamicSound.cs
new file mode 100644
index 0000000..f91f63d
--- /dev/null
+++ b/Client/Assembly-CSharp/DynamicSound.cs
@@ -0,0 +1,26 @@
+using System;
+using UnityEngine;
+
+public class DynamicSound : ISoundPlayer
+{
+ public string Name { get; set; }
+
+ public AudioSource Player { get; set; }
+
+ public DynamicSound.GetDynamicsFunction volumeFunc;
+
+ public delegate void GetDynamicsFunction(AudioSource source, float dt);
+
+ public void Update(float dt)
+ {
+ this.volumeFunc(this.Player, dt);
+ }
+
+ public void SetTarget(AudioClip clip, DynamicSound.GetDynamicsFunction volumeFunc)
+ {
+ this.volumeFunc = volumeFunc;
+ this.Player.clip = clip;
+ this.volumeFunc(this.Player, 1f);
+ this.Player.Play();
+ }
+}
diff --git a/Client/Assembly-CSharp/Effects.cs b/Client/Assembly-CSharp/Effects.cs
new file mode 100644
index 0000000..56b3efe
--- /dev/null
+++ b/Client/Assembly-CSharp/Effects.cs
@@ -0,0 +1,248 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+public static class Effects
+{
+ private static HashSet<Transform> activeShakes = new HashSet<Transform>();
+
+ public static IEnumerator Wait(float duration)
+ {
+ for (float t = 0f; t < duration; t += Time.deltaTime)
+ {
+ yield return null;
+ }
+ yield break;
+ }
+
+ public static IEnumerator All(params IEnumerator[] items)
+ {
+ Stack<IEnumerator>[] enums = new Stack<IEnumerator>[items.Length];
+ for (int i = 0; i < items.Length; i++)
+ {
+ enums[i] = new Stack<IEnumerator>();
+ enums[i].Push(items[i]);
+ }
+ int num;
+ for (int cap = 0; cap < 100000; cap = num)
+ {
+ bool flag = false;
+ for (int j = 0; j < enums.Length; j++)
+ {
+ if (enums[j].Count > 0)
+ {
+ flag = true;
+ IEnumerator enumerator = enums[j].Peek();
+ if (enumerator.MoveNext())
+ {
+ if (enumerator.Current is IEnumerator)
+ {
+ enums[j].Push((IEnumerator)enumerator.Current);
+ }
+ }
+ else
+ {
+ enums[j].Pop();
+ }
+ }
+ }
+ if (!flag)
+ {
+ break;
+ }
+ yield return null;
+ num = cap + 1;
+ }
+ yield break;
+ }
+
+ internal static IEnumerator ScaleIn(Transform self, float source, float target, float duration)
+ {
+ if (!self)
+ {
+ yield break;
+ }
+ Vector3 localScale = default(Vector3);
+ for (float t = 0f; t < duration; t += Time.deltaTime)
+ {
+ localScale.x = (localScale.y = (localScale.z = Mathf.SmoothStep(source, target, t / duration)));
+ self.localScale = localScale;
+ yield return null;
+ }
+ localScale.z = target;
+ localScale.y = target;
+ localScale.x = target;
+ self.localScale = localScale;
+ yield break;
+ }
+
+ internal static IEnumerator CycleColors(SpriteRenderer self, Color source, Color target, float rate, float duration)
+ {
+ if (!self)
+ {
+ yield break;
+ }
+ self.enabled = true;
+ for (float t = 0f; t < duration; t += Time.deltaTime)
+ {
+ float t2 = Mathf.Sin(t * 3.1415927f / rate) / 2f + 0.5f;
+ self.color = Color.Lerp(source, target, t2);
+ yield return null;
+ }
+ self.color = source;
+ yield break;
+ }
+
+ internal static IEnumerator PulseColor(SpriteRenderer self, Color source, Color target, float duration = 0.5f)
+ {
+ if (!self)
+ {
+ yield break;
+ }
+ self.enabled = true;
+ for (float t = 0f; t < duration; t += Time.deltaTime)
+ {
+ self.color = Color.Lerp(target, source, t / duration);
+ yield return null;
+ }
+ self.color = source;
+ yield break;
+ }
+
+ internal static IEnumerator PulseColor(TextRenderer self, Color source, Color target, float duration = 0.5f)
+ {
+ if (!self)
+ {
+ yield break;
+ }
+ for (float t = 0f; t < duration; t += Time.deltaTime)
+ {
+ self.Color = Color.Lerp(target, source, t / duration);
+ yield return null;
+ }
+ self.Color = source;
+ yield break;
+ }
+
+ public static IEnumerator ColorFade(SpriteRenderer self, Color source, Color target, float duration)
+ {
+ if (!self)
+ {
+ yield break;
+ }
+ self.enabled = true;
+ for (float t = 0f; t < duration; t += Time.deltaTime)
+ {
+ self.color = Color.Lerp(source, target, t / duration);
+ yield return null;
+ }
+ self.color = target;
+ yield break;
+ }
+
+ public static IEnumerator Rotate2D(Transform target, float source, float dest, float duration = 0.75f)
+ {
+ Vector3 temp = target.localEulerAngles;
+ for (float time = 0f; time < duration; time += Time.deltaTime)
+ {
+ float t = time / duration;
+ temp.z = Mathf.SmoothStep(source, dest, t);
+ target.localEulerAngles = temp;
+ yield return null;
+ }
+ temp.z = dest;
+ target.localEulerAngles = temp;
+ yield break;
+ }
+
+ public static IEnumerator Slide2D(Transform target, Vector2 source, Vector2 dest, float duration = 0.75f)
+ {
+ Vector3 temp = default(Vector3);
+ temp.z = target.localPosition.z;
+ for (float time = 0f; time < duration; time += Time.deltaTime)
+ {
+ float t = time / duration;
+ temp.x = Mathf.SmoothStep(source.x, dest.x, t);
+ temp.y = Mathf.SmoothStep(source.y, dest.y, t);
+ target.localPosition = temp;
+ yield return null;
+ }
+ temp.x = dest.x;
+ temp.y = dest.y;
+ target.localPosition = temp;
+ yield break;
+ }
+
+ public static IEnumerator Bounce(Transform target, float duration = 0.3f, float height = 0.15f)
+ {
+ if (!target)
+ {
+ yield break;
+ }
+ Vector3 origin = target.localPosition;
+ Vector3 temp = origin;
+ for (float timer = 0f; timer < duration; timer += Time.deltaTime)
+ {
+ float num = timer / duration;
+ float num2 = 1f - num;
+ temp.y = origin.y + height * Mathf.Abs(Mathf.Sin(num * 3.1415927f * 3f)) * num2;
+ if (!target)
+ {
+ yield break;
+ }
+ target.localPosition = temp;
+ yield return null;
+ }
+ if (target)
+ {
+ target.transform.localPosition = origin;
+ }
+ yield break;
+ }
+
+ public static IEnumerator Shake(Transform target, float duration = 0.75f, float halfWidth = 0.25f)
+ {
+ if (Effects.activeShakes.Add(target))
+ {
+ Vector3 origin = target.localPosition;
+ for (float timer = 0f; timer < duration; timer += Time.deltaTime)
+ {
+ float num = timer / duration;
+ target.localPosition = origin + Vector3.right * (halfWidth * Mathf.Sin(num * 30f) * (1f - num));
+ yield return null;
+ }
+ target.transform.localPosition = origin;
+ Effects.activeShakes.Remove(target);
+ origin = default(Vector3);
+ }
+ yield break;
+ }
+
+ public static IEnumerator Bloop(float delay, Transform target, float duration = 0.5f)
+ {
+ for (float t = 0f; t < delay; t += Time.deltaTime)
+ {
+ yield return null;
+ }
+ Vector3 localScale = default(Vector3);
+ for (float t = 0f; t < duration; t += Time.deltaTime)
+ {
+ float z = Effects.ElasticOut(t, duration);
+ localScale.x = (localScale.y = (localScale.z = z));
+ target.localScale = localScale;
+ yield return null;
+ }
+ localScale.x = (localScale.y = (localScale.z = 1f));
+ target.localScale = localScale;
+ yield break;
+ }
+
+ private static float ElasticOut(float time, float duration)
+ {
+ time /= duration;
+ float num = time * time;
+ float num2 = num * time;
+ return 33f * num2 * num + -106f * num * num + 126f * num2 + -67f * num + 15f * time;
+ }
+}
diff --git a/Client/Assembly-CSharp/ElectricTask.cs b/Client/Assembly-CSharp/ElectricTask.cs
new file mode 100644
index 0000000..1480462
--- /dev/null
+++ b/Client/Assembly-CSharp/ElectricTask.cs
@@ -0,0 +1,82 @@
+using System;
+using System.Linq;
+using System.Text;
+using UnityEngine;
+
+public class ElectricTask : SabotageTask
+{
+ public override int TaskStep
+ {
+ get
+ {
+ if (!this.isComplete)
+ {
+ return 0;
+ }
+ return 1;
+ }
+ }
+
+ public override bool IsComplete
+ {
+ get
+ {
+ return this.isComplete;
+ }
+ }
+
+ private bool isComplete;
+
+ private SwitchSystem system;
+
+ private bool even;
+
+ public override void Initialize()
+ {
+ ShipStatus instance = ShipStatus.Instance;
+ this.system = (SwitchSystem)instance.Systems[SystemTypes.Electrical];
+ base.SetupArrows();
+ }
+
+ private void FixedUpdate()
+ {
+ if (this.isComplete)
+ {
+ return;
+ }
+ if (this.system.ExpectedSwitches == this.system.ActualSwitches)
+ {
+ this.Complete();
+ }
+ }
+
+ public override bool ValidConsole(global::Console console)
+ {
+ return console.TaskTypes.Contains(TaskTypes.FixLights);
+ }
+
+ public override void Complete()
+ {
+ this.isComplete = true;
+ PlayerControl.LocalPlayer.RemoveTask(this);
+ if (this.didContribute)
+ {
+ StatsManager instance = StatsManager.Instance;
+ uint sabsFixed = instance.SabsFixed;
+ instance.SabsFixed = sabsFixed + 1U;
+ }
+ }
+
+ public override void AppendTaskText(StringBuilder sb)
+ {
+ this.even = !this.even;
+ Color color = this.even ? Color.yellow : Color.red;
+ sb.Append(color.ToTextColor());
+ sb.Append(DestroyableSingleton<TranslationController>.Instance.GetString(TaskTypes.FixLights));
+ sb.AppendLine(" (%" + (int)(this.system.Level * 100f) + ")[]");
+ for (int i = 0; i < this.Arrows.Length; i++)
+ {
+ this.Arrows[i].image.color = color;
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/EmergencyMinigame.cs b/Client/Assembly-CSharp/EmergencyMinigame.cs
new file mode 100644
index 0000000..5b6bff6
--- /dev/null
+++ b/Client/Assembly-CSharp/EmergencyMinigame.cs
@@ -0,0 +1,120 @@
+using System;
+using System.Collections;
+using System.Linq;
+using UnityEngine;
+
+public class EmergencyMinigame : Minigame
+{
+ public SpriteRenderer ClosedLid;
+
+ public SpriteRenderer OpenLid;
+
+ public Transform meetingButton;
+
+ public TextRenderer StatusText;
+
+ public TextRenderer NumberText;
+
+ public bool ButtonActive = true;
+
+ public AudioClip ButtonSound;
+
+ private int state;
+
+ public const int MinEmergencyTime = 15;
+
+ public override void Begin(PlayerTask task)
+ {
+ base.Begin(task);
+ this.Update();
+ }
+
+ public void Update()
+ {
+ if (ShipStatus.Instance.Timer < 15f || ShipStatus.Instance.EmergencyCooldown > 0f)
+ {
+ int num = Mathf.CeilToInt(15f - ShipStatus.Instance.Timer);
+ num = Mathf.Max(Mathf.CeilToInt(ShipStatus.Instance.EmergencyCooldown), num);
+ this.ButtonActive = false;
+ this.StatusText.Text = DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.EmergencyNotReady, Array.Empty<object>());
+ this.NumberText.Text = num + "s";
+ this.ClosedLid.gameObject.SetActive(true);
+ this.OpenLid.gameObject.SetActive(false);
+ return;
+ }
+ if (!PlayerControl.LocalPlayer.myTasks.Any(new Func<PlayerTask, bool>(PlayerTask.TaskIsEmergency)))
+ {
+ if (this.state == 1)
+ {
+ return;
+ }
+ this.state = 1;
+ int remainingEmergencies = PlayerControl.LocalPlayer.RemainingEmergencies;
+ this.StatusText.Text = DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.EmergencyCount, new object[]
+ {
+ PlayerControl.LocalPlayer.Data.PlayerName
+ });
+ this.NumberText.Text = remainingEmergencies.ToString();
+ this.ButtonActive = (remainingEmergencies > 0);
+ this.ClosedLid.gameObject.SetActive(!this.ButtonActive);
+ this.OpenLid.gameObject.SetActive(this.ButtonActive);
+ return;
+ }
+ else
+ {
+ if (this.state == 2)
+ {
+ return;
+ }
+ this.state = 2;
+ this.ButtonActive = false;
+ this.StatusText.Text = DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.EmergencyDuringCrisis, Array.Empty<object>());
+ this.NumberText.Text = string.Empty;
+ this.ClosedLid.gameObject.SetActive(true);
+ this.OpenLid.gameObject.SetActive(false);
+ return;
+ }
+ }
+
+ public void CallMeeting()
+ {
+ if (!PlayerControl.LocalPlayer.myTasks.Any(new Func<PlayerTask, bool>(PlayerTask.TaskIsEmergency)) && PlayerControl.LocalPlayer.RemainingEmergencies > 0 && this.ButtonActive)
+ {
+ this.StatusText.Text = DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.EmergencyRequested, Array.Empty<object>());
+ if (Constants.ShouldPlaySfx())
+ {
+ SoundManager.Instance.PlaySound(this.ButtonSound, false, 1f);
+ }
+ PlayerControl.LocalPlayer.CmdReportDeadBody(null);
+ this.ButtonActive = false;
+ }
+ }
+
+ private float easeOutElastic(float t)
+ {
+ float num = 0.3f;
+ return Mathf.Pow(2f, -10f * t) * Mathf.Sin((t - num / 4f) * 6.2831855f / num) + 1f;
+ }
+
+ protected override IEnumerator CoAnimateOpen()
+ {
+ for (float timer = 0f; timer < 0.2f; timer += Time.deltaTime)
+ {
+ float t = timer / 0.2f;
+ base.transform.localPosition = new Vector3(0f, Mathf.SmoothStep(-8f, 0f, t), -50f);
+ yield return null;
+ }
+ base.transform.localPosition = new Vector3(0f, 0f, -50f);
+ Vector3 meetingPos = this.meetingButton.localPosition;
+ for (float timer = 0f; timer < 0.1f; timer += Time.deltaTime)
+ {
+ float num = timer / 0.1f;
+ meetingPos.y = Mathf.Sin(3.1415927f * num) * 1f / (num * 5f + 4f) - 0.882f;
+ this.meetingButton.localPosition = meetingPos;
+ yield return null;
+ }
+ meetingPos.y = -0.882f;
+ this.meetingButton.localPosition = meetingPos;
+ yield break;
+ }
+}
diff --git a/Client/Assembly-CSharp/EmptyGarbageMinigame.cs b/Client/Assembly-CSharp/EmptyGarbageMinigame.cs
new file mode 100644
index 0000000..679d683
--- /dev/null
+++ b/Client/Assembly-CSharp/EmptyGarbageMinigame.cs
@@ -0,0 +1,195 @@
+using System;
+using System.Collections;
+using System.Linq;
+using UnityEngine;
+
+public class EmptyGarbageMinigame : Minigame
+{
+ private const float GrinderVolume = 0.8f;
+
+ public FloatRange HandleRange = new FloatRange(-0.65f, 0.65f);
+
+ public Vector2Range SpawnRange;
+
+ public Collider2D Blocker;
+
+ public AreaEffector2D Popper;
+
+ public Collider2D Handle;
+
+ public SpriteRenderer Bars;
+
+ private Controller controller = new Controller();
+
+ private bool finished;
+
+ public int NumObjects = 15;
+
+ private SpriteRenderer[] Objects;
+
+ public SpriteRenderer[] GarbagePrefabs;
+
+ public SpriteRenderer[] LeafPrefabs;
+
+ public SpriteRenderer[] SpecialObjectPrefabs;
+
+ public AudioClip LeverDown;
+
+ public AudioClip LeverUp;
+
+ public AudioClip GrinderStart;
+
+ public AudioClip GrinderLoop;
+
+ public AudioClip GrinderEnd;
+
+ public override void Begin(PlayerTask task)
+ {
+ base.Begin(task);
+ int i = 0;
+ this.Objects = new SpriteRenderer[this.NumObjects];
+ RandomFill<SpriteRenderer> randomFill = new RandomFill<SpriteRenderer>();
+ NormalPlayerTask myNormTask = this.MyNormTask;
+ if (myNormTask != null && myNormTask.taskStep == 0)
+ {
+ if (this.MyNormTask.StartAt == SystemTypes.Cafeteria)
+ {
+ randomFill.Set(this.GarbagePrefabs);
+ }
+ else
+ {
+ randomFill.Set(this.LeafPrefabs);
+ }
+ }
+ else
+ {
+ randomFill.Set(this.GarbagePrefabs.Union(this.LeafPrefabs));
+ while (i < this.SpecialObjectPrefabs.Length)
+ {
+ SpriteRenderer spriteRenderer = this.Objects[i] = UnityEngine.Object.Instantiate<SpriteRenderer>(this.SpecialObjectPrefabs[i]);
+ spriteRenderer.transform.SetParent(base.transform);
+ spriteRenderer.transform.localPosition = this.SpawnRange.Next();
+ i++;
+ }
+ }
+ while (i < this.Objects.Length)
+ {
+ SpriteRenderer spriteRenderer2 = this.Objects[i] = UnityEngine.Object.Instantiate<SpriteRenderer>(randomFill.Get());
+ spriteRenderer2.transform.SetParent(base.transform);
+ Vector3 vector = this.SpawnRange.Next();
+ vector.z = FloatRange.Next(-0.5f, 0.5f);
+ spriteRenderer2.transform.localPosition = vector;
+ spriteRenderer2.GetComponent<SpriteRenderer>().color = Color.Lerp(Color.white, Color.black, (vector.z + 0.5f) * 0.7f);
+ i++;
+ }
+ }
+
+ public void Update()
+ {
+ if (this.amClosing != Minigame.CloseState.None)
+ {
+ return;
+ }
+ this.controller.Update();
+ Vector3 localPosition = this.Handle.transform.localPosition;
+ float num = this.HandleRange.ReverseLerp(localPosition.y);
+ switch (this.controller.CheckDrag(this.Handle, false))
+ {
+ case DragState.NoTouch:
+ localPosition.y = Mathf.Lerp(localPosition.y, this.HandleRange.max, num + Time.deltaTime * 15f);
+ break;
+ case DragState.Dragging:
+ if (!this.finished)
+ {
+ if (num > 0.5f)
+ {
+ Vector2 vector = this.controller.DragPosition - base.transform.position;
+ float num2 = this.HandleRange.ReverseLerp(this.HandleRange.Clamp(vector.y));
+ localPosition.y = this.HandleRange.Lerp(num2 / 2f + 0.5f);
+ }
+ else
+ {
+ localPosition.y = Mathf.Lerp(localPosition.y, this.HandleRange.min, num + Time.deltaTime * 15f);
+ if (this.Blocker.enabled)
+ {
+ if (Constants.ShouldPlaySfx())
+ {
+ SoundManager.Instance.PlaySound(this.LeverDown, false, 1f);
+ SoundManager.Instance.PlaySound(this.GrinderStart, false, 0.8f);
+ SoundManager.Instance.StopSound(this.GrinderEnd);
+ SoundManager.Instance.StopSound(this.GrinderLoop);
+ }
+ this.Blocker.enabled = false;
+ base.StopAllCoroutines();
+ base.StartCoroutine(this.PopObjects());
+ base.StartCoroutine(this.AnimateObjects());
+ }
+ }
+ }
+ break;
+ case DragState.Released:
+ if (!this.Blocker.enabled)
+ {
+ this.Blocker.enabled = true;
+ if (Constants.ShouldPlaySfx())
+ {
+ SoundManager.Instance.PlaySound(this.LeverUp, false, 1f);
+ SoundManager.Instance.StopSound(this.GrinderStart);
+ SoundManager.Instance.StopSound(this.GrinderLoop);
+ SoundManager.Instance.PlaySound(this.GrinderEnd, false, 0.8f);
+ }
+ }
+ if (!this.finished)
+ {
+ if (this.Objects.All((SpriteRenderer o) => !o))
+ {
+ this.finished = true;
+ this.MyNormTask.NextStep();
+ base.StartCoroutine(base.CoStartClose(0.75f));
+ }
+ }
+ break;
+ }
+ if (Constants.ShouldPlaySfx() && !this.Blocker.enabled && !SoundManager.Instance.SoundIsPlaying(this.GrinderStart))
+ {
+ SoundManager.Instance.PlaySound(this.GrinderLoop, true, 0.8f);
+ }
+ this.Handle.transform.localPosition = localPosition;
+ Vector3 localScale = this.Bars.transform.localScale;
+ localScale.y = this.HandleRange.ChangeRange(localPosition.y, -1f, 1f);
+ this.Bars.transform.localScale = localScale;
+ }
+
+ private IEnumerator PopObjects()
+ {
+ this.Popper.enabled = true;
+ yield return new WaitForSeconds(0.05f);
+ this.Popper.enabled = false;
+ yield break;
+ }
+
+ private IEnumerator AnimateObjects()
+ {
+ Vector3 pos = base.transform.localPosition;
+ for (float t = 3f; t > 0f; t -= Time.deltaTime)
+ {
+ float d = t / 3f;
+ base.transform.localPosition = pos + Vector2Range.NextEdge() * d * 0.1f;
+ yield return null;
+ }
+ yield break;
+ }
+
+ public override void Close()
+ {
+ SoundManager.Instance.StopSound(this.GrinderStart);
+ SoundManager.Instance.StopSound(this.GrinderLoop);
+ SoundManager.Instance.StopSound(this.GrinderEnd);
+ if (this.MyNormTask && this.MyNormTask.IsComplete)
+ {
+ ShipStatus.Instance.OpenHatch();
+ PlayerControl.LocalPlayer.RpcPlayAnimation((byte)this.MyTask.TaskType);
+ }
+ base.Close();
+ }
+}
diff --git a/Client/Assembly-CSharp/EndGameManager.cs b/Client/Assembly-CSharp/EndGameManager.cs
new file mode 100644
index 0000000..7380913
--- /dev/null
+++ b/Client/Assembly-CSharp/EndGameManager.cs
@@ -0,0 +1,236 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using Assets.CoreScripts;
+using InnerNet;
+using UnityEngine;
+
+public class EndGameManager : DestroyableSingleton<EndGameManager>
+{
+ public TextRenderer WinText;
+
+ public MeshRenderer BackgroundBar;
+
+ public MeshRenderer Foreground;
+
+ public FloatRange ForegroundRadius;
+
+ public SpriteRenderer FrontMost;
+
+ public PoolablePlayer PlayerPrefab;
+
+ public Sprite GhostSprite;
+
+ public SpriteRenderer PlayAgainButton;
+
+ public SpriteRenderer ExitButton;
+
+ public AudioClip DisconnectStinger;
+
+ public AudioClip CrewStinger;
+
+ public AudioClip ImpostorStinger;
+
+ public float BaseY = -0.25f;
+
+ private float stingerTime;
+
+ public void Start()
+ {
+ if (TempData.showAd && !SaveManager.BoughtNoAds)
+ {
+ AdPlayer.RequestInterstitial();
+ }
+ this.SetEverythingUp();
+ base.StartCoroutine(this.CoBegin());
+ base.Invoke("ShowButtons", 1.1f);
+ }
+
+ private void ShowButtons()
+ {
+ this.FrontMost.gameObject.SetActive(false);
+ this.PlayAgainButton.gameObject.SetActive(true);
+ this.ExitButton.gameObject.SetActive(true);
+ }
+
+ private void SetEverythingUp()
+ {
+ StatsManager instance = StatsManager.Instance;
+ uint gamesFinished = instance.GamesFinished;
+ instance.GamesFinished = gamesFinished + 1U;
+ bool flag = TempData.DidHumansWin(TempData.EndReason);
+ if (TempData.EndReason == GameOverReason.ImpostorDisconnect)
+ {
+ StatsManager.Instance.AddDrawReason(TempData.EndReason);
+ this.WinText.Text = DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.ImpostorDisconnected, Array.Empty<object>());
+ SoundManager.Instance.PlaySound(this.DisconnectStinger, false, 1f);
+ }
+ else if (TempData.EndReason == GameOverReason.HumansDisconnect)
+ {
+ StatsManager.Instance.AddDrawReason(TempData.EndReason);
+ this.WinText.Text = DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.CrewmatesDisconnected, Array.Empty<object>());
+ SoundManager.Instance.PlaySound(this.DisconnectStinger, false, 1f);
+ }
+ else
+ {
+ if (TempData.winners.Any((WinningPlayerData h) => h.IsYou))
+ {
+ StatsManager.Instance.AddWinReason(TempData.EndReason);
+ this.WinText.Text = DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.Victory, Array.Empty<object>());
+ this.BackgroundBar.material.SetColor("_Color", Palette.CrewmateBlue);
+ WinningPlayerData winningPlayerData = TempData.winners.FirstOrDefault((WinningPlayerData h) => h.IsYou);
+ if (winningPlayerData != null)
+ {
+ DestroyableSingleton<Telemetry>.Instance.WonGame(winningPlayerData.ColorId, winningPlayerData.HatId);
+ }
+ }
+ else
+ {
+ StatsManager.Instance.AddLoseReason(TempData.EndReason);
+ this.WinText.Text = DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.Defeat, Array.Empty<object>());
+ this.WinText.Color = Color.red;
+ }
+ if (flag)
+ {
+ SoundManager.Instance.PlayDynamicSound("Stinger", this.CrewStinger, false, new DynamicSound.GetDynamicsFunction(this.GetStingerVol), false);
+ }
+ else
+ {
+ SoundManager.Instance.PlayDynamicSound("Stinger", this.ImpostorStinger, false, new DynamicSound.GetDynamicsFunction(this.GetStingerVol), false);
+ }
+ }
+ List<WinningPlayerData> list = TempData.winners.OrderBy(delegate(WinningPlayerData b)
+ {
+ if (!b.IsYou)
+ {
+ return 0;
+ }
+ return -1;
+ }).ToList<WinningPlayerData>();
+ for (int i = 0; i < list.Count; i++)
+ {
+ WinningPlayerData winningPlayerData2 = list[i];
+ int num = (i % 2 == 0) ? -1 : 1;
+ int num2 = (i + 1) / 2;
+ float num3 = 1f - (float)num2 * 0.075f;
+ float num4 = 1f - (float)num2 * 0.035f;
+ float num5 = (float)((i == 0) ? -8 : -1);
+ PoolablePlayer poolablePlayer = UnityEngine.Object.Instantiate<PoolablePlayer>(this.PlayerPrefab, base.transform);
+ poolablePlayer.transform.localPosition = new Vector3(0.8f * (float)num * (float)num2 * num4, this.BaseY - 0.25f + (float)num2 * 0.1f, num5 + (float)num2 * 0.01f) * 1.25f;
+ Vector3 vector = new Vector3(num3, num3, num3) * 1.25f;
+ poolablePlayer.transform.localScale = vector;
+ if (winningPlayerData2.IsDead)
+ {
+ poolablePlayer.Body.sprite = this.GhostSprite;
+ poolablePlayer.SetDeadFlipX(i % 2 != 0);
+ }
+ else
+ {
+ poolablePlayer.SetFlipX(i % 2 == 0);
+ }
+ if (!winningPlayerData2.IsDead)
+ {
+ DestroyableSingleton<HatManager>.Instance.SetSkin(poolablePlayer.SkinSlot, winningPlayerData2.SkinId);
+ }
+ else
+ {
+ poolablePlayer.HatSlot.color = new Color(1f, 1f, 1f, 0.5f);
+ }
+ PlayerControl.SetPlayerMaterialColors(winningPlayerData2.ColorId, poolablePlayer.Body);
+ PlayerControl.SetHatImage(winningPlayerData2.HatId, poolablePlayer.HatSlot);
+ PlayerControl.SetPetImage(winningPlayerData2.PetId, winningPlayerData2.ColorId, poolablePlayer.PetSlot);
+ if (flag)
+ {
+ poolablePlayer.NameText.gameObject.SetActive(false);
+ }
+ else
+ {
+ poolablePlayer.NameText.Text = winningPlayerData2.Name;
+ if (winningPlayerData2.IsImpostor)
+ {
+ poolablePlayer.NameText.Color = Palette.ImpostorRed;
+ }
+ poolablePlayer.NameText.transform.localScale = vector.Inv();
+ }
+ }
+ }
+
+ private void GetStingerVol(AudioSource source, float dt)
+ {
+ this.stingerTime += dt * 0.75f;
+ source.volume = Mathf.Clamp(1f / this.stingerTime, 0f, 1f);
+ }
+
+ public IEnumerator CoBegin()
+ {
+ Color c = this.WinText.Color;
+ Color fade = Color.black;
+ Color white = Color.white;
+ Vector3 titlePos = this.WinText.transform.localPosition;
+ float timer = 0f;
+ while (timer < 3f)
+ {
+ timer += Time.deltaTime;
+ float num = Mathf.Min(1f, timer / 3f);
+ this.Foreground.material.SetFloat("_Rad", this.ForegroundRadius.ExpOutLerp(num * 2f));
+ fade.a = Mathf.Lerp(1f, 0f, num * 3f);
+ this.FrontMost.color = fade;
+ c.a = Mathf.Clamp(FloatRange.ExpOutLerp(num, 0f, 1f), 0f, 1f);
+ this.WinText.Color = c;
+ titlePos.y = 2.7f - num * 0.3f;
+ this.WinText.transform.localPosition = titlePos;
+ yield return null;
+ }
+ this.FrontMost.gameObject.SetActive(false);
+ yield break;
+ }
+
+ public void NextGame()
+ {
+ this.PlayAgainButton.gameObject.SetActive(false);
+ this.ExitButton.gameObject.SetActive(false);
+ if (TempData.showAd && !SaveManager.BoughtNoAds)
+ {
+ TempData.showAd = false;
+ AdPlayer.ShowInterstitial(this, true);
+ return;
+ }
+ base.StartCoroutine(this.CoJoinGame());
+ }
+
+ public IEnumerator CoJoinGame()
+ {
+ AmongUsClient.Instance.JoinGame();
+ yield return EndGameManager.WaitWithTimeout(() => AmongUsClient.Instance.ClientId >= 0);
+ if (AmongUsClient.Instance.ClientId < 0)
+ {
+ AmongUsClient.Instance.ExitGame(AmongUsClient.Instance.LastDisconnectReason);
+ }
+ yield break;
+ }
+
+ public void Exit()
+ {
+ this.PlayAgainButton.gameObject.SetActive(false);
+ this.ExitButton.gameObject.SetActive(false);
+ if (TempData.showAd && !SaveManager.BoughtNoAds)
+ {
+ TempData.showAd = false;
+ AdPlayer.ShowInterstitial(this, false);
+ return;
+ }
+ AmongUsClient.Instance.ExitGame(DisconnectReasons.ExitGame);
+ }
+
+ public static IEnumerator WaitWithTimeout(Func<bool> success)
+ {
+ float timer = 0f;
+ while (timer < 5f && !success())
+ {
+ yield return null;
+ timer += Time.deltaTime;
+ }
+ yield break;
+ }
+}
diff --git a/Client/Assembly-CSharp/EngineBehaviour.cs b/Client/Assembly-CSharp/EngineBehaviour.cs
new file mode 100644
index 0000000..87bdccf
--- /dev/null
+++ b/Client/Assembly-CSharp/EngineBehaviour.cs
@@ -0,0 +1,48 @@
+using System;
+using UnityEngine;
+
+public class EngineBehaviour : MonoBehaviour
+{
+ public AudioClip ElectricSound;
+
+ public AudioClip SteamSound;
+
+ public float SoundDistance = 5f;
+
+ public void PlayElectricSound()
+ {
+ if (Constants.ShouldPlaySfx())
+ {
+ SoundManager.Instance.PlayDynamicSound("EngineShock" + base.name, this.ElectricSound, false, new DynamicSound.GetDynamicsFunction(this.GetSoundDistance), false);
+ }
+ }
+
+ public void PlaySteamSound()
+ {
+ if (Constants.ShouldPlaySfx())
+ {
+ float pitch = FloatRange.Next(0.7f, 1.1f);
+ SoundManager.Instance.PlayDynamicSound("EngineSteam" + base.name, this.SteamSound, false, delegate(AudioSource p, float d)
+ {
+ this.GetSoundDistance(p, d, pitch);
+ }, false);
+ }
+ }
+
+ private void GetSoundDistance(AudioSource player, float dt)
+ {
+ this.GetSoundDistance(player, dt, 1f);
+ }
+
+ private void GetSoundDistance(AudioSource player, float dt, float pitch)
+ {
+ float num = 1f;
+ if (PlayerControl.LocalPlayer)
+ {
+ float num2 = Vector2.Distance(base.transform.position, PlayerControl.LocalPlayer.GetTruePosition());
+ num = 1f - num2 / this.SoundDistance;
+ }
+ player.volume = num * 0.8f;
+ player.pitch = pitch;
+ }
+}
diff --git a/Client/Assembly-CSharp/EnterCodeMinigame.cs b/Client/Assembly-CSharp/EnterCodeMinigame.cs
new file mode 100644
index 0000000..4bbc0ef
--- /dev/null
+++ b/Client/Assembly-CSharp/EnterCodeMinigame.cs
@@ -0,0 +1,121 @@
+using System;
+using System.Collections;
+using UnityEngine;
+
+public class EnterCodeMinigame : Minigame
+{
+ public TextRenderer NumberText;
+
+ public TextRenderer TargetText;
+
+ public int number;
+
+ public string numString = string.Empty;
+
+ private bool animating;
+
+ public SpriteRenderer AcceptButton;
+
+ private bool done;
+
+ private int targetNumber;
+
+ public void EnterDigit(int i)
+ {
+ if (this.animating)
+ {
+ return;
+ }
+ if (this.done)
+ {
+ return;
+ }
+ if (this.NumberText.Text.Length >= 5)
+ {
+ base.StartCoroutine(this.BlinkAccept());
+ return;
+ }
+ this.numString += i;
+ this.number = this.number * 10 + i;
+ this.NumberText.Text = this.numString;
+ }
+
+ public void ClearDigits()
+ {
+ if (this.animating)
+ {
+ return;
+ }
+ this.number = 0;
+ this.numString = string.Empty;
+ this.NumberText.Text = string.Empty;
+ }
+
+ public void AcceptDigits()
+ {
+ if (this.animating)
+ {
+ return;
+ }
+ base.StartCoroutine(this.Animate());
+ }
+
+ public override void Begin(PlayerTask task)
+ {
+ base.Begin(task);
+ this.targetNumber = BitConverter.ToInt32(this.MyNormTask.Data, 0);
+ this.NumberText.Text = string.Empty;
+ this.TargetText.Text = this.targetNumber.ToString("D5");
+ }
+
+ private IEnumerator BlinkAccept()
+ {
+ int num;
+ for (int i = 0; i < 5; i = num)
+ {
+ this.AcceptButton.color = Color.gray;
+ yield return null;
+ yield return null;
+ this.AcceptButton.color = Color.white;
+ yield return null;
+ yield return null;
+ num = i + 1;
+ }
+ yield break;
+ }
+
+ private IEnumerator Animate()
+ {
+ this.animating = true;
+ WaitForSeconds wait = new WaitForSeconds(0.1f);
+ yield return wait;
+ this.NumberText.Text = string.Empty;
+ yield return wait;
+ if (this.targetNumber == this.number)
+ {
+ this.done = true;
+ this.NumberText.Text = "OK";
+ yield return wait;
+ this.NumberText.Text = string.Empty;
+ yield return wait;
+ this.NumberText.Text = "OK";
+ yield return wait;
+ this.NumberText.Text = string.Empty;
+ yield return base.CoStartClose(0.5f);
+ }
+ else
+ {
+ this.NumberText.Text = "Bad";
+ yield return wait;
+ this.NumberText.Text = string.Empty;
+ yield return wait;
+ this.NumberText.Text = "Bad";
+ yield return wait;
+ this.numString = string.Empty;
+ this.number = 0;
+ this.NumberText.Text = this.numString;
+ }
+ this.animating = false;
+ yield break;
+ }
+}
diff --git a/Client/Assembly-CSharp/ExileController.cs b/Client/Assembly-CSharp/ExileController.cs
new file mode 100644
index 0000000..4a52a4d
--- /dev/null
+++ b/Client/Assembly-CSharp/ExileController.cs
@@ -0,0 +1,160 @@
+using System;
+using System.Collections;
+using System.Linq;
+using UnityEngine;
+
+public class ExileController : MonoBehaviour
+{
+ public static ExileController Instance;
+
+ public TextRenderer ImpostorText;
+
+ public TextRenderer Text;
+
+ public SpriteRenderer Player;
+
+ public SpriteRenderer PlayerHat;
+
+ public SpriteRenderer PlayerSkin;
+
+ public AnimationCurve LerpCurve;
+
+ public float Duration = 7f;
+
+ public AudioClip TextSound;
+
+ private string completeString = string.Empty;
+
+ private GameData.PlayerInfo exiled;
+
+ public void Begin(GameData.PlayerInfo exiled, bool tie)
+ {
+ ExileController.Instance = this;
+ this.exiled = exiled;
+ this.Text.gameObject.SetActive(false);
+ this.Text.Text = string.Empty;
+ int num = GameData.Instance.AllPlayers.Count((GameData.PlayerInfo p) => p.IsImpostor && !p.IsDead && !p.Disconnected);
+ if (exiled != null)
+ {
+ int num2 = GameData.Instance.AllPlayers.Count((GameData.PlayerInfo p) => p.IsImpostor);
+ if (exiled.IsImpostor)
+ {
+ if (num2 > 1)
+ {
+ this.completeString = DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.ExileTextPP, new object[]
+ {
+ exiled.PlayerName
+ });
+ }
+ else
+ {
+ this.completeString = DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.ExileTextSP, new object[]
+ {
+ exiled.PlayerName
+ });
+ }
+ }
+ else if (num2 > 1)
+ {
+ this.completeString = DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.ExileTextPN, new object[]
+ {
+ exiled.PlayerName
+ });
+ }
+ else
+ {
+ this.completeString = DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.ExileTextSN, new object[]
+ {
+ exiled.PlayerName
+ });
+ }
+ PlayerControl.SetPlayerMaterialColors((int)exiled.ColorId, this.Player);
+ PlayerControl.SetHatImage(exiled.HatId, this.PlayerHat);
+ this.PlayerSkin.sprite = DestroyableSingleton<HatManager>.Instance.GetSkinById(exiled.SkinId).EjectFrame;
+ if (exiled.IsImpostor)
+ {
+ num--;
+ }
+ }
+ else
+ {
+ if (tie)
+ {
+ this.completeString = DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.NoExileTie, Array.Empty<object>());
+ }
+ else
+ {
+ this.completeString = DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.NoExileSkip, Array.Empty<object>());
+ }
+ this.Player.gameObject.SetActive(false);
+ }
+ if (num == 1)
+ {
+ this.ImpostorText.Text = DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.ImpostorsRemainS, new object[]
+ {
+ num
+ });
+ }
+ else
+ {
+ this.ImpostorText.Text = DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.ImpostorsRemainP, new object[]
+ {
+ num
+ });
+ }
+ base.StartCoroutine(this.Animate());
+ }
+
+ private IEnumerator Animate()
+ {
+ yield return DestroyableSingleton<HudManager>.Instance.CoFadeFullScreen(Color.black, Color.clear, 0.2f);
+ yield return new WaitForSeconds(1f);
+ float d = Camera.main.orthographicSize * Camera.main.aspect + 1f;
+ Vector2 left = Vector2.left * d;
+ Vector2 right = Vector2.right * d;
+ for (float t = 0f; t <= this.Duration; t += Time.deltaTime)
+ {
+ float num = t / this.Duration;
+ this.Player.transform.localPosition = Vector2.Lerp(left, right, this.LerpCurve.Evaluate(num));
+ float z = (t + 0.75f) * 25f / Mathf.Exp(t * 0.75f + 1f);
+ this.Player.transform.Rotate(new Vector3(0f, 0f, z));
+ if (num >= 0.3f)
+ {
+ int num2 = (int)(Mathf.Min(1f, (num - 0.3f) / 0.3f) * (float)this.completeString.Length);
+ if (num2 > this.Text.Text.Length)
+ {
+ this.Text.Text = this.completeString.Substring(0, num2);
+ this.Text.gameObject.SetActive(true);
+ if (this.completeString[num2 - 1] != ' ')
+ {
+ SoundManager.Instance.PlaySoundImmediate(this.TextSound, false, 0.8f, 1f);
+ }
+ }
+ }
+ yield return null;
+ }
+ this.Text.Text = this.completeString;
+ this.ImpostorText.gameObject.SetActive(true);
+ yield return Effects.Bloop(0f, this.ImpostorText.transform, 0.5f);
+ yield return new WaitForSeconds(0.5f);
+ yield return DestroyableSingleton<HudManager>.Instance.CoFadeFullScreen(Color.clear, Color.black, 0.2f);
+ if (this.exiled != null)
+ {
+ PlayerControl @object = this.exiled.Object;
+ if (@object != null)
+ {
+ @object.Exiled();
+ }
+ }
+ if (DestroyableSingleton<TutorialManager>.InstanceExists || !ShipStatus.Instance.IsGameOverDueToDeath())
+ {
+ DestroyableSingleton<HudManager>.Instance.StartCoroutine(DestroyableSingleton<HudManager>.Instance.CoFadeFullScreen(Color.black, Color.clear, 0.2f));
+ PlayerControl.LocalPlayer.SetKillTimer(PlayerControl.GameOptions.KillCooldown);
+ ShipStatus.Instance.EmergencyCooldown = (float)PlayerControl.GameOptions.EmergencyCooldown;
+ Camera.main.GetComponent<FollowerCamera>().Locked = false;
+ DestroyableSingleton<HudManager>.Instance.SetHudActive(true);
+ }
+ UnityEngine.Object.Destroy(base.gameObject);
+ yield break;
+ }
+}
diff --git a/Client/Assembly-CSharp/ExitGameButton.cs b/Client/Assembly-CSharp/ExitGameButton.cs
new file mode 100644
index 0000000..6fbbc35
--- /dev/null
+++ b/Client/Assembly-CSharp/ExitGameButton.cs
@@ -0,0 +1,24 @@
+using System;
+using InnerNet;
+using UnityEngine;
+
+public class ExitGameButton : MonoBehaviour
+{
+ public void Start()
+ {
+ if (!DestroyableSingleton<HudManager>.InstanceExists)
+ {
+ base.gameObject.SetActive(false);
+ }
+ }
+
+ public void OnClick()
+ {
+ if (AmongUsClient.Instance)
+ {
+ AmongUsClient.Instance.ExitGame(DisconnectReasons.ExitGame);
+ return;
+ }
+ SceneChanger.ChangeScene("MainMenu");
+ }
+}
diff --git a/Client/Assembly-CSharp/Extensions.cs b/Client/Assembly-CSharp/Extensions.cs
new file mode 100644
index 0000000..a653cea
--- /dev/null
+++ b/Client/Assembly-CSharp/Extensions.cs
@@ -0,0 +1,409 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using UnityEngine;
+
+public static class Extensions
+{
+ private static string[] ByteHex = (from x in Enumerable.Range(0, 256)
+ select x.ToString("X2")).ToArray<string>();
+
+ public static void TrimEnd(this StringBuilder self)
+ {
+ for (int i = self.Length - 1; i >= 0; i--)
+ {
+ char c = self[i];
+ if (c != ' ' && c != '\t' && c != '\n' && c != '\r')
+ {
+ break;
+ }
+ int length = self.Length;
+ self.Length = length - 1;
+ }
+ }
+
+ public static void AddUnique<T>(this IList<T> self, T item)
+ {
+ if (!self.Contains(item))
+ {
+ self.Add(item);
+ }
+ }
+
+ public static string ToTextColor(this Color c)
+ {
+ return string.Concat(new string[]
+ {
+ "[",
+ Extensions.ByteHex[(int)((byte)(c.r * 255f))],
+ Extensions.ByteHex[(int)((byte)(c.g * 255f))],
+ Extensions.ByteHex[(int)((byte)(c.b * 255f))],
+ Extensions.ByteHex[(int)((byte)(c.a * 255f))],
+ "]"
+ });
+ }
+
+ public static int ToInteger(this Color c, bool alpha)
+ {
+ if (alpha)
+ {
+ return (int)((byte)(c.r * 256f)) << 24 | (int)((byte)(c.g * 256f)) << 16 | (int)((byte)(c.b * 256f)) << 8 | (int)((byte)(c.a * 256f));
+ }
+ return (int)((byte)(c.r * 256f)) << 16 | (int)((byte)(c.g * 256f)) << 8 | (int)((byte)(c.b * 256f));
+ }
+
+ public static bool HasAnyBit(this int self, int bit)
+ {
+ return (self & bit) != 0;
+ }
+
+ public static bool HasAnyBit(this byte self, byte bit)
+ {
+ return (self & bit) > 0;
+ }
+
+ public static bool HasBit(this byte self, byte bit)
+ {
+ return (self & bit) == bit;
+ }
+
+ public static int BitCount(this byte self)
+ {
+ int num = 0;
+ for (int i = 0; i < 8; i++)
+ {
+ if ((1 << i & (int)self) != 0)
+ {
+ num++;
+ }
+ }
+ return num;
+ }
+
+ public static int IndexOf<T>(this T[] self, T item) where T : class
+ {
+ for (int i = 0; i < self.Length; i++)
+ {
+ if (self[i] == item)
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public static int IndexOfMin<T>(this T[] self, Func<T, float> comparer)
+ {
+ float num = float.MaxValue;
+ int result = -1;
+ for (int i = 0; i < self.Length; i++)
+ {
+ float num2 = comparer(self[i]);
+ if (num2 <= num)
+ {
+ result = i;
+ num = num2;
+ }
+ }
+ return result;
+ }
+
+ public static int IndexOfMax<T>(this T[] self, Func<T, int> comparer, out bool tie)
+ {
+ tie = false;
+ int num = int.MinValue;
+ int result = -1;
+ for (int i = 0; i < self.Length; i++)
+ {
+ int num2 = comparer(self[i]);
+ if (num2 > num)
+ {
+ result = i;
+ num = num2;
+ tie = false;
+ }
+ else if (num2 == num)
+ {
+ tie = true;
+ result = -1;
+ }
+ }
+ return result;
+ }
+
+ public static void SetAll<T>(this IList<T> self, T value)
+ {
+ for (int i = 0; i < self.Count; i++)
+ {
+ self[i] = value;
+ }
+ }
+
+ public static void AddAll<T>(this List<T> self, IList<T> other)
+ {
+ int num = self.Count + other.Count;
+ if (self.Capacity < num)
+ {
+ self.Capacity = num;
+ }
+ for (int i = 0; i < other.Count; i++)
+ {
+ self.Add(other[i]);
+ }
+ }
+
+ public static void RemoveDupes<T>(this IList<T> self) where T : class
+ {
+ for (int i = 0; i < self.Count; i++)
+ {
+ T t = self[i];
+ for (int j = self.Count - 1; j > i; j--)
+ {
+ if (self[j] == t)
+ {
+ self.RemoveAt(j);
+ }
+ }
+ }
+ }
+
+ public static void Shuffle<T>(this IList<T> self)
+ {
+ for (int i = 0; i < self.Count - 1; i++)
+ {
+ T value = self[i];
+ int index = UnityEngine.Random.Range(i, self.Count);
+ self[i] = self[index];
+ self[index] = value;
+ }
+ }
+
+ public static void Shuffle<T>(this System.Random r, IList<T> self)
+ {
+ for (int i = 0; i < self.Count; i++)
+ {
+ T value = self[i];
+ int index = r.Next(self.Count);
+ self[i] = self[index];
+ self[index] = value;
+ }
+ }
+
+ public static T[] RandomSet<T>(this IList<T> self, int length)
+ {
+ T[] array = new T[length];
+ self.RandomFill(array);
+ return array;
+ }
+
+ public static void RandomFill<T>(this IList<T> self, T[] target)
+ {
+ HashSet<int> hashSet = new HashSet<int>();
+ for (int i = 0; i < target.Length; i++)
+ {
+ int num;
+ do
+ {
+ num = self.RandomIdx<T>();
+ }
+ while (hashSet.Contains(num));
+ target[i] = self[num];
+ hashSet.Add(num);
+ if (hashSet.Count == self.Count)
+ {
+ return;
+ }
+ }
+ }
+
+ public static int RandomIdx<T>(this IList<T> self)
+ {
+ return UnityEngine.Random.Range(0, self.Count);
+ }
+
+ public static int RandomIdx<T>(this IEnumerable<T> self)
+ {
+ return UnityEngine.Random.Range(0, self.Count<T>());
+ }
+
+ public static T Random<T>(this IEnumerable<T> self)
+ {
+ return self.ToArray<T>().Random<T>();
+ }
+
+ public static T Random<T>(this IList<T> self)
+ {
+ if (self.Count > 0)
+ {
+ return self[UnityEngine.Random.Range(0, self.Count)];
+ }
+ return default(T);
+ }
+
+ public static Vector2 Div(this Vector2 a, Vector2 b)
+ {
+ return new Vector2(a.x / b.x, a.y / b.y);
+ }
+
+ public static Vector2 Mul(this Vector2 a, Vector2 b)
+ {
+ return new Vector2(a.x * b.x, a.y * b.y);
+ }
+
+ public static Vector3 Mul(this Vector3 a, Vector3 b)
+ {
+ return new Vector3(a.x * b.x, a.y * b.y, a.z * b.z);
+ }
+
+ public static Vector3 Inv(this Vector3 a)
+ {
+ return new Vector3(1f / a.x, 1f / a.y, 1f / a.z);
+ }
+
+ public static Rect Lerp(this Rect source, Rect target, float t)
+ {
+ return new Rect
+ {
+ position = Vector2.Lerp(source.position, target.position, t),
+ size = Vector2.Lerp(source.size, target.size, t)
+ };
+ }
+
+ public static void ForEach<T>(this IList<T> self, Action<T> todo)
+ {
+ for (int i = 0; i < self.Count; i++)
+ {
+ todo(self[i]);
+ }
+ }
+
+ public static T Max<T>(this IList<T> self, Func<T, float> comparer)
+ {
+ T t = self.First<T>();
+ float num = comparer(t);
+ for (int i = 0; i < self.Count; i++)
+ {
+ T t2 = self[i];
+ float num2 = comparer(t2);
+ if (num < num2 || (num == num2 && UnityEngine.Random.value > 0.5f))
+ {
+ num = num2;
+ t = t2;
+ }
+ }
+ return t;
+ }
+
+ public static T Max<T>(this IList<T> self, Func<T, decimal> comparer)
+ {
+ T t = self.First<T>();
+ decimal d = comparer(t);
+ for (int i = 0; i < self.Count; i++)
+ {
+ T t2 = self[i];
+ decimal num = comparer(t2);
+ if (d < num || (d == num && UnityEngine.Random.value > 0.5f))
+ {
+ d = num;
+ t = t2;
+ }
+ }
+ return t;
+ }
+
+ public static int Wrap(this int self, int max)
+ {
+ if (self >= 0)
+ {
+ return self % max;
+ }
+ return (self + -(self / max) * max + max) % max;
+ }
+
+ public static int IndexOf<T>(this T[] self, Predicate<T> pred)
+ {
+ for (int i = 0; i < self.Length; i++)
+ {
+ if (pred(self[i]))
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public static Vector2 MapToRectangle(this Vector2 del, Vector2 widthAndHeight)
+ {
+ del = del.normalized;
+ if (Mathf.Abs(del.x) > Mathf.Abs(del.y))
+ {
+ return new Vector2(Mathf.Sign(del.x) * widthAndHeight.x, del.y * widthAndHeight.y / 0.70710677f);
+ }
+ return new Vector2(del.x * widthAndHeight.x / 0.70710677f, Mathf.Sign(del.y) * widthAndHeight.y);
+ }
+
+ public static float AngleSignedRad(this Vector2 vector1, Vector2 vector2)
+ {
+ return Mathf.Atan2(vector2.y, vector2.x) - Mathf.Atan2(vector1.y, vector1.x);
+ }
+
+ public static float AngleSigned(this Vector2 vector1, Vector2 vector2)
+ {
+ return vector1.AngleSignedRad(vector2) * 57.29578f;
+ }
+
+ public static Vector2 Rotate(this Vector2 self, float degrees)
+ {
+ float f = 0.017453292f * degrees;
+ float num = Mathf.Cos(f);
+ float num2 = Mathf.Sin(f);
+ return new Vector2(self.x * num - num2 * self.y, self.x * num2 + num * self.y);
+ }
+
+ public static Vector3 RotateY(this Vector3 self, float degrees)
+ {
+ float f = 0.017453292f * degrees;
+ float num = Mathf.Cos(f);
+ float num2 = Mathf.Sin(f);
+ return new Vector3(self.x * num - num2 * self.z, self.y, self.x * num2 + num * self.z);
+ }
+
+ public static bool TryToEnum<TEnum>(this string strEnumValue, out TEnum enumValue)
+ {
+ enumValue = default(TEnum);
+ if (!Enum.IsDefined(typeof(TEnum), strEnumValue))
+ {
+ return false;
+ }
+ enumValue = (TEnum)((object)Enum.Parse(typeof(TEnum), strEnumValue));
+ return true;
+ }
+
+ public static TEnum ToEnum<TEnum>(this string strEnumValue)
+ {
+ if (!Enum.IsDefined(typeof(TEnum), strEnumValue))
+ {
+ return default(TEnum);
+ }
+ return (TEnum)((object)Enum.Parse(typeof(TEnum), strEnumValue));
+ }
+
+ public static TEnum ToEnum<TEnum>(this string strEnumValue, TEnum defaultValue)
+ {
+ if (!Enum.IsDefined(typeof(TEnum), strEnumValue))
+ {
+ return defaultValue;
+ }
+ return (TEnum)((object)Enum.Parse(typeof(TEnum), strEnumValue));
+ }
+
+ public static bool IsNullOrWhiteSpace(this string s)
+ {
+ if (s == null)
+ {
+ return true;
+ }
+ return !s.Any((char c) => !char.IsWhiteSpace(c));
+ }
+}
diff --git a/Client/Assembly-CSharp/FindAGameManager.cs b/Client/Assembly-CSharp/FindAGameManager.cs
new file mode 100644
index 0000000..b428861
--- /dev/null
+++ b/Client/Assembly-CSharp/FindAGameManager.cs
@@ -0,0 +1,124 @@
+using System;
+using System.Collections.Generic;
+using InnerNet;
+using UnityEngine;
+using UnityEngine.SceneManagement;
+
+public class FindAGameManager : DestroyableSingleton<FindAGameManager>, IGameListHandler
+{
+ private const float RefreshTime = 5f;
+
+ private float timer;
+
+ public ObjectPoolBehavior buttonPool;
+
+ public SpinAnimator RefreshSpinner;
+
+ public Scroller TargetArea;
+
+ public float ButtonStart = 1.75f;
+
+ public float ButtonHeight = 0.6f;
+
+ public const bool showPrivate = false;
+
+ private class GameSorter : IComparer<GameListing>
+ {
+ public static readonly FindAGameManager.GameSorter Instance = new FindAGameManager.GameSorter();
+
+ public int Compare(GameListing x, GameListing y)
+ {
+ return -x.PlayerCount.CompareTo(y.PlayerCount);
+ }
+ }
+
+ public void ResetTimer()
+ {
+ this.timer = 5f;
+ this.RefreshSpinner.Appear();
+ this.RefreshSpinner.StartPulse();
+ }
+
+ public void Start()
+ {
+ if (!AmongUsClient.Instance)
+ {
+ AmongUsClient.Instance = UnityEngine.Object.FindObjectOfType<AmongUsClient>();
+ if (!AmongUsClient.Instance)
+ {
+ SceneManager.LoadScene("MMOnline");
+ return;
+ }
+ }
+ AmongUsClient.Instance.GameListHandlers.Add(this);
+ AmongUsClient.Instance.RequestGameList(false, SaveManager.GameSearchOptions);
+ }
+
+ public void Update()
+ {
+ this.timer += Time.deltaTime;
+ GameOptionsData gameSearchOptions = SaveManager.GameSearchOptions;
+ if ((this.timer < 0f || this.timer > 5f) && gameSearchOptions.MapId != 0)
+ {
+ this.RefreshSpinner.Appear();
+ }
+ else
+ {
+ this.RefreshSpinner.Disappear();
+ }
+ if (Input.GetKeyUp(KeyCode.Escape))
+ {
+ this.ExitGame();
+ }
+ }
+
+ public void RefreshList()
+ {
+ if (this.timer > 5f)
+ {
+ this.timer = -5f;
+ this.RefreshSpinner.Play();
+ AmongUsClient.Instance.RequestGameList(false, SaveManager.GameSearchOptions);
+ }
+ }
+
+ public override void OnDestroy()
+ {
+ if (AmongUsClient.Instance)
+ {
+ AmongUsClient.Instance.GameListHandlers.Remove(this);
+ }
+ base.OnDestroy();
+ }
+
+ public void HandleList(int totalGames, List<GameListing> availableGames)
+ {
+ Debug.Log(string.Format("TotalGames: {0}\tAvailable: {1}", totalGames, availableGames.Count));
+ this.RefreshSpinner.Disappear();
+ this.timer = 0f;
+ availableGames.Sort(FindAGameManager.GameSorter.Instance);
+ while (this.buttonPool.activeChildren.Count > availableGames.Count)
+ {
+ PoolableBehavior poolableBehavior = this.buttonPool.activeChildren[this.buttonPool.activeChildren.Count - 1];
+ poolableBehavior.OwnerPool.Reclaim(poolableBehavior);
+ }
+ while (this.buttonPool.activeChildren.Count < availableGames.Count)
+ {
+ this.buttonPool.Get<PoolableBehavior>().transform.SetParent(this.TargetArea.Inner);
+ }
+ Vector3 vector = new Vector3(0f, this.ButtonStart, -1f);
+ for (int i = 0; i < this.buttonPool.activeChildren.Count; i++)
+ {
+ MatchMakerGameButton matchMakerGameButton = (MatchMakerGameButton)this.buttonPool.activeChildren[i];
+ matchMakerGameButton.SetGame(availableGames[i]);
+ matchMakerGameButton.transform.localPosition = vector;
+ vector.y -= this.ButtonHeight;
+ }
+ this.TargetArea.YBounds.max = Mathf.Max(0f, -vector.y - this.ButtonStart);
+ }
+
+ public void ExitGame()
+ {
+ AmongUsClient.Instance.ExitGame(DisconnectReasons.ExitGame);
+ }
+}
diff --git a/Client/Assembly-CSharp/FindGameButton.cs b/Client/Assembly-CSharp/FindGameButton.cs
new file mode 100644
index 0000000..4b3eef9
--- /dev/null
+++ b/Client/Assembly-CSharp/FindGameButton.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Collections;
+using InnerNet;
+using PowerTools;
+using UnityEngine;
+using UnityEngine.SceneManagement;
+
+public class FindGameButton : MonoBehaviour, IConnectButton
+{
+ public SpriteAnim connectIcon;
+
+ public AnimationClip connectClip;
+
+ public void OnClick()
+ {
+ if (NameTextBehaviour.Instance.ShakeIfInvalid())
+ {
+ return;
+ }
+ if (StatsManager.Instance.AmBanned)
+ {
+ AmongUsClient.Instance.LastDisconnectReason = DisconnectReasons.IntentionalLeaving;
+ DestroyableSingleton<DisconnectPopup>.Instance.Show();
+ return;
+ }
+ if (!DestroyableSingleton<MatchMaker>.Instance.Connecting(this))
+ {
+ return;
+ }
+ AmongUsClient.Instance.GameMode = GameModes.OnlineGame;
+ AmongUsClient.Instance.MainMenuScene = "MMOnline";
+ base.StartCoroutine(this.ConnectForFindGame());
+ }
+
+ private IEnumerator ConnectForFindGame()
+ {
+ AmongUsClient.Instance.SetEndpoint(DestroyableSingleton<ServerManager>.Instance.OnlineNetAddress, 22023);
+ AmongUsClient.Instance.OnlineScene = "OnlineGame";
+ AmongUsClient.Instance.mode = MatchMakerModes.Client;
+ yield return AmongUsClient.Instance.CoConnect();
+ if (AmongUsClient.Instance.LastDisconnectReason != DisconnectReasons.ExitGame)
+ {
+ DestroyableSingleton<MatchMaker>.Instance.NotConnecting();
+ }
+ else
+ {
+ AmongUsClient.Instance.HostId = AmongUsClient.Instance.ClientId;
+ SceneManager.LoadScene("FindAGame");
+ }
+ yield break;
+ }
+
+ public void StartIcon()
+ {
+ this.connectIcon.Play(this.connectClip, 1f);
+ }
+
+ public void StopIcon()
+ {
+ this.connectIcon.Stop();
+ this.connectIcon.GetComponent<SpriteRenderer>().sprite = null;
+ }
+}
diff --git a/Client/Assembly-CSharp/FingerBehaviour.cs b/Client/Assembly-CSharp/FingerBehaviour.cs
new file mode 100644
index 0000000..b39ad65
--- /dev/null
+++ b/Client/Assembly-CSharp/FingerBehaviour.cs
@@ -0,0 +1,101 @@
+using System;
+using System.Collections;
+using UnityEngine;
+
+public class FingerBehaviour : MonoBehaviour
+{
+ public SpriteRenderer Finger;
+
+ public SpriteRenderer Click;
+
+ public float liftedAngle = -20f;
+
+ public static class Quadratic
+ {
+ public static float InOut(float k)
+ {
+ if (k < 0f)
+ {
+ k = 0f;
+ }
+ if (k > 1f)
+ {
+ k = 1f;
+ }
+ if ((k *= 2f) < 1f)
+ {
+ return 0.5f * k * k;
+ }
+ return -0.5f * ((k -= 1f) * (k - 2f) - 1f);
+ }
+ }
+
+ public IEnumerator DoClick(float duration)
+ {
+ for (float time = 0f; time < duration; time += Time.deltaTime)
+ {
+ float num = time / duration;
+ if (num < 0.4f)
+ {
+ float num2 = num / 0.4f;
+ num2 = num2 * 2f - 1f;
+ if (num2 < 0f)
+ {
+ float fingerAngle = Mathf.Lerp(this.liftedAngle, this.liftedAngle * 2f, 1f + Mathf.Abs(num2));
+ this.SetFingerAngle(fingerAngle);
+ }
+ else
+ {
+ float fingerAngle2 = Mathf.Lerp(this.liftedAngle * 2f, 0f, num2);
+ this.SetFingerAngle(fingerAngle2);
+ }
+ }
+ else if (num < 0.7f)
+ {
+ this.ClickOn();
+ }
+ else
+ {
+ float t = (num - 0.7f) / 0.3f;
+ this.Click.enabled = false;
+ float fingerAngle3 = Mathf.Lerp(0f, this.liftedAngle, t);
+ this.SetFingerAngle(fingerAngle3);
+ }
+ yield return null;
+ }
+ this.ClickOff();
+ yield break;
+ }
+
+ private void SetFingerAngle(float angle)
+ {
+ this.Finger.transform.localRotation = Quaternion.Euler(0f, 0f, angle);
+ }
+
+ public void ClickOff()
+ {
+ this.Click.enabled = false;
+ this.SetFingerAngle(this.liftedAngle);
+ }
+
+ public void ClickOn()
+ {
+ this.Click.enabled = true;
+ this.SetFingerAngle(0f);
+ }
+
+ public IEnumerator MoveTo(Vector2 target, float duration)
+ {
+ Vector3 startPos = base.transform.position;
+ Vector3 targetPos = target;
+ targetPos.z = startPos.z;
+ for (float time = 0f; time < duration; time += Time.deltaTime)
+ {
+ float t = time / duration;
+ base.transform.position = Vector3.Lerp(startPos, targetPos, t);
+ yield return null;
+ }
+ base.transform.position = targetPos;
+ yield break;
+ }
+}
diff --git a/Client/Assembly-CSharp/FixedActionConsole.cs b/Client/Assembly-CSharp/FixedActionConsole.cs
new file mode 100644
index 0000000..63707bb
--- /dev/null
+++ b/Client/Assembly-CSharp/FixedActionConsole.cs
@@ -0,0 +1,64 @@
+using System;
+using UnityEngine;
+using UnityEngine.UI;
+
+public class FixedActionConsole : MonoBehaviour, IUsable
+{
+ public float UsableDistance
+ {
+ get
+ {
+ return this.usableDistance;
+ }
+ }
+
+ public float PercentCool
+ {
+ get
+ {
+ return 0f;
+ }
+ }
+
+ public float usableDistance = 1f;
+
+ public SpriteRenderer Image;
+
+ public Button.ButtonClickedEvent OnUse;
+
+ public void SetOutline(bool on, bool mainTarget)
+ {
+ if (this.Image)
+ {
+ this.Image.material.SetFloat("_Outline", (float)(on ? 1 : 0));
+ this.Image.material.SetColor("_OutlineColor", Color.white);
+ this.Image.material.SetColor("_AddColor", mainTarget ? Color.white : Color.clear);
+ }
+ }
+
+ public float CanUse(GameData.PlayerInfo pc, out bool canUse, out bool couldUse)
+ {
+ float num = float.MaxValue;
+ PlayerControl @object = pc.Object;
+ couldUse = (pc.Object.CanMove && !pc.IsDead);
+ canUse = couldUse;
+ if (canUse)
+ {
+ num = Vector2.Distance(@object.GetTruePosition(), base.transform.position);
+ canUse &= (num <= this.UsableDistance);
+ }
+ return num;
+ }
+
+ public void Use()
+ {
+ bool flag;
+ bool flag2;
+ this.CanUse(PlayerControl.LocalPlayer.Data, out flag, out flag2);
+ if (!flag)
+ {
+ return;
+ }
+ this.OnUse.Invoke();
+ }
+}
diff --git a/Client/Assembly-CSharp/FlatWaveBehaviour.cs b/Client/Assembly-CSharp/FlatWaveBehaviour.cs
new file mode 100644
index 0000000..4f10d5a
--- /dev/null
+++ b/Client/Assembly-CSharp/FlatWaveBehaviour.cs
@@ -0,0 +1,75 @@
+using System;
+using UnityEngine;
+
+[RequireComponent(typeof(MeshFilter))]
+[RequireComponent(typeof(MeshRenderer))]
+public class FlatWaveBehaviour : MonoBehaviour
+{
+ public int NumPoints = 128;
+
+ public FloatRange Width;
+
+ public FloatRange Delta;
+
+ public float Center;
+
+ private Mesh mesh;
+
+ private Vector3[] vecs;
+
+ public float TickRate = 0.1f;
+
+ private float timer;
+
+ public int Skip = 3;
+
+ [Range(0f, 1f)]
+ public float NoiseP = 0.5f;
+
+ public void Start()
+ {
+ this.mesh = new Mesh();
+ base.GetComponent<MeshFilter>().mesh = this.mesh;
+ this.mesh.MarkDynamic();
+ this.vecs = new Vector3[this.NumPoints];
+ int[] array = new int[this.NumPoints];
+ for (int i = 0; i < this.vecs.Length; i++)
+ {
+ Vector3 vector = this.vecs[i];
+ vector.x = this.Width.Lerp((float)i / (float)this.vecs.Length);
+ vector.y = this.Center;
+ if (BoolRange.Next(this.NoiseP))
+ {
+ vector.y += this.Delta.Next();
+ }
+ this.vecs[i] = vector;
+ array[i] = i;
+ }
+ this.mesh.vertices = this.vecs;
+ this.mesh.SetIndices(array, MeshTopology.LineStrip, 0);
+ }
+
+ public void Update()
+ {
+ this.timer += Time.deltaTime;
+ if (this.timer > this.TickRate)
+ {
+ this.timer = 0f;
+ for (int i = 0; i < this.vecs.Length - this.Skip; i++)
+ {
+ this.vecs[i].y = this.vecs[i + this.Skip].y;
+ }
+ for (int j = 1; j <= this.Skip; j++)
+ {
+ this.vecs[this.vecs.Length - j].y = this.Center;
+ if (BoolRange.Next(this.NoiseP))
+ {
+ Vector3[] array = this.vecs;
+ int num = this.vecs.Length - j;
+ array[num].y = array[num].y + this.Delta.Next();
+ }
+ }
+ this.mesh.vertices = this.vecs;
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/FloatRange.cs b/Client/Assembly-CSharp/FloatRange.cs
new file mode 100644
index 0000000..ca7cfbd
--- /dev/null
+++ b/Client/Assembly-CSharp/FloatRange.cs
@@ -0,0 +1,159 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+[Serializable]
+public class FloatRange
+{
+ public float Last { get; private set; }
+
+ public float Width
+ {
+ get
+ {
+ return this.max - this.min;
+ }
+ }
+
+ public float min;
+
+ public float max;
+
+ public FloatRange(float min, float max)
+ {
+ this.min = min;
+ this.max = max;
+ }
+
+ public float ChangeRange(float y, float min, float max)
+ {
+ return Mathf.Lerp(min, max, (y - this.min) / this.Width);
+ }
+
+ public float Clamp(float value)
+ {
+ return Mathf.Clamp(value, this.min, this.max);
+ }
+
+ public bool Contains(float t)
+ {
+ return this.min <= t && this.max >= t;
+ }
+
+ public float CubicLerp(float v)
+ {
+ if (this.min >= this.max)
+ {
+ return this.min;
+ }
+ v = Mathf.Clamp(0f, 1f, v);
+ return v * v * v * (this.max - this.min) + this.min;
+ }
+
+ public float EitherOr()
+ {
+ if (UnityEngine.Random.value <= 0.5f)
+ {
+ return this.max;
+ }
+ return this.min;
+ }
+
+ public float LerpUnclamped(float v)
+ {
+ return Mathf.LerpUnclamped(this.min, this.max, v);
+ }
+
+ public float Lerp(float v)
+ {
+ return Mathf.Lerp(this.min, this.max, v);
+ }
+
+ public float ExpOutLerp(float v)
+ {
+ return this.Lerp(1f - Mathf.Pow(2f, -10f * v));
+ }
+
+ public static float ExpOutLerp(float v, float min, float max)
+ {
+ return Mathf.Lerp(min, max, 1f - Mathf.Pow(2f, -10f * v));
+ }
+
+ public static float Next(float min, float max)
+ {
+ return UnityEngine.Random.Range(min, max);
+ }
+
+ public float Next()
+ {
+ return this.Last = UnityEngine.Random.Range(this.min, this.max);
+ }
+
+ public IEnumerable<float> Range(int numStops)
+ {
+ float num;
+ for (float i = 0f; i <= (float)numStops; i = num)
+ {
+ yield return Mathf.Lerp(this.min, this.max, i / (float)numStops);
+ num = i + 1f;
+ }
+ yield break;
+ }
+
+ public IEnumerable<float> RandomRange(int numStops)
+ {
+ float num;
+ for (float i = 0f; i <= (float)numStops; i = num)
+ {
+ yield return this.Next();
+ num = i + 1f;
+ }
+ yield break;
+ }
+
+ internal float ReverseLerp(float t)
+ {
+ return Mathf.Clamp((t - this.min) / this.Width, 0f, 1f);
+ }
+
+ public static float ReverseLerp(float t, float min, float max)
+ {
+ float num = max - min;
+ return Mathf.Clamp((t - min) / num, 0f, 1f);
+ }
+
+ public IEnumerable<float> SpreadToEdges(int stops)
+ {
+ return FloatRange.SpreadToEdges(this.min, this.max, stops);
+ }
+
+ public IEnumerable<float> SpreadEvenly(int stops)
+ {
+ return FloatRange.SpreadEvenly(this.min, this.max, stops);
+ }
+
+ public static IEnumerable<float> SpreadToEdges(float min, float max, int stops)
+ {
+ if (stops == 1)
+ {
+ yield break;
+ }
+ int num;
+ for (int i = 0; i < stops; i = num)
+ {
+ yield return Mathf.Lerp(min, max, (float)i / ((float)stops - 1f));
+ num = i + 1;
+ }
+ yield break;
+ }
+
+ public static IEnumerable<float> SpreadEvenly(float min, float max, int stops)
+ {
+ float step = 1f / ((float)stops + 1f);
+ for (float i = step; i < 1f; i += step)
+ {
+ yield return Mathf.Lerp(min, max, i);
+ }
+ yield break;
+ }
+}
diff --git a/Client/Assembly-CSharp/FollowerCamera.cs b/Client/Assembly-CSharp/FollowerCamera.cs
new file mode 100644
index 0000000..3184542
--- /dev/null
+++ b/Client/Assembly-CSharp/FollowerCamera.cs
@@ -0,0 +1,54 @@
+using System;
+using System.Collections;
+using UnityEngine;
+
+internal class FollowerCamera : MonoBehaviour
+{
+ public MonoBehaviour Target;
+
+ public Vector2 Offset;
+
+ public bool Locked;
+
+ public float shakeAmount;
+
+ public float shakePeriod = 1f;
+
+ public void FixedUpdate()
+ {
+ if (this.Target && !this.Locked)
+ {
+ base.transform.position = Vector3.Lerp(base.transform.position, this.Target.transform.position + this.Offset, 5f * Time.deltaTime);
+ if (this.shakeAmount > 0f)
+ {
+ float num = Mathf.PerlinNoise(0.5f, Time.time * this.shakePeriod) * 2f - 1f;
+ float num2 = Mathf.PerlinNoise(Time.time * this.shakePeriod, 0.5f) * 2f - 1f;
+ base.transform.Translate(num * this.shakeAmount, num2 * this.shakeAmount, 0f);
+ }
+ }
+ }
+
+ public void ShakeScreen(float duration, float severity)
+ {
+ base.StartCoroutine(this.CoShakeScreen(duration, severity));
+ }
+
+ private IEnumerator CoShakeScreen(float duration, float severity)
+ {
+ WaitForFixedUpdate wait = new WaitForFixedUpdate();
+ for (float t = duration; t > 0f; t -= Time.fixedDeltaTime)
+ {
+ float d = t / duration;
+ this.Offset = UnityEngine.Random.insideUnitCircle * d * severity;
+ yield return wait;
+ }
+ this.Offset = Vector2.zero;
+ yield break;
+ }
+
+ internal void SetTarget(MonoBehaviour target)
+ {
+ this.Target = target;
+ base.transform.position = this.Target.transform.position + this.Offset;
+ }
+}
diff --git a/Client/Assembly-CSharp/FontCache.cs b/Client/Assembly-CSharp/FontCache.cs
new file mode 100644
index 0000000..91dc7a0
--- /dev/null
+++ b/Client/Assembly-CSharp/FontCache.cs
@@ -0,0 +1,78 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class FontCache : MonoBehaviour
+{
+ public static FontCache Instance;
+
+ private Dictionary<string, FontData> cache = new Dictionary<string, FontData>();
+
+ public List<FontExtensionData> extraData = new List<FontExtensionData>();
+
+ public List<TextAsset> DefaultFonts = new List<TextAsset>();
+
+ public List<Material> DefaultFontMaterials = new List<Material>();
+
+ public void OnEnable()
+ {
+ if (!FontCache.Instance)
+ {
+ FontCache.Instance = this;
+ UnityEngine.Object.DontDestroyOnLoad(base.gameObject);
+ return;
+ }
+ if (FontCache.Instance != null)
+ {
+ UnityEngine.Object.Destroy(base.gameObject);
+ }
+ }
+
+ public void SetFont(TextRenderer self, string name)
+ {
+ if (self.FontData.name == name)
+ {
+ return;
+ }
+ for (int i = 0; i < this.DefaultFonts.Count; i++)
+ {
+ if (this.DefaultFonts[i].name == name)
+ {
+ MeshRenderer component = self.GetComponent<MeshRenderer>();
+ Material material = component.material;
+ self.FontData = this.DefaultFonts[i];
+ component.sharedMaterial = this.DefaultFontMaterials[i];
+ component.material.SetColor("_OutlineColor", material.GetColor("_OutlineColor"));
+ component.material.SetInt("_Mask", material.GetInt("_Mask"));
+ return;
+ }
+ }
+ }
+
+ public FontData LoadFont(TextAsset dataSrc)
+ {
+ if (this.cache == null)
+ {
+ this.cache = new Dictionary<string, FontData>();
+ }
+ FontData fontData;
+ if (this.cache.TryGetValue(dataSrc.name, out fontData))
+ {
+ return fontData;
+ }
+ int num = this.extraData.FindIndex((FontExtensionData ed) => ed.FontName.Equals(dataSrc.name, StringComparison.OrdinalIgnoreCase));
+ FontExtensionData eData = null;
+ if (num >= 0)
+ {
+ eData = this.extraData[num];
+ }
+ fontData = FontCache.LoadFontUncached(dataSrc, eData);
+ this.cache[dataSrc.name] = fontData;
+ return fontData;
+ }
+
+ public static FontData LoadFontUncached(TextAsset dataSrc, FontExtensionData eData = null)
+ {
+ return FontLoader.FromBinary(dataSrc, eData);
+ }
+}
diff --git a/Client/Assembly-CSharp/FontData.cs b/Client/Assembly-CSharp/FontData.cs
new file mode 100644
index 0000000..896d74c
--- /dev/null
+++ b/Client/Assembly-CSharp/FontData.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+[Serializable]
+public class FontData
+{
+ public Vector2 TextureSize = new Vector2(256f, 256f);
+
+ public List<Vector4> bounds = new List<Vector4>();
+
+ public List<Vector3> offsets = new List<Vector3>();
+
+ public List<Vector4> Channels = new List<Vector4>();
+
+ public Dictionary<int, int> charMap;
+
+ public float LineHeight;
+
+ public Dictionary<int, Dictionary<int, float>> kernings;
+
+ public float GetKerning(int last, int cur)
+ {
+ Dictionary<int, float> dictionary;
+ float result;
+ if (this.kernings.TryGetValue(last, out dictionary) && dictionary.TryGetValue(cur, out result))
+ {
+ return result;
+ }
+ return 0f;
+ }
+}
diff --git a/Client/Assembly-CSharp/FontExtensionData.cs b/Client/Assembly-CSharp/FontExtensionData.cs
new file mode 100644
index 0000000..8978b88
--- /dev/null
+++ b/Client/Assembly-CSharp/FontExtensionData.cs
@@ -0,0 +1,56 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+[CreateAssetMenu]
+public class FontExtensionData : ScriptableObject
+{
+ public string FontName;
+
+ public List<KerningPair> kernings = new List<KerningPair>();
+
+ public List<OffsetAdjustment> Offsets = new List<OffsetAdjustment>();
+
+ public void AdjustKernings(FontData target)
+ {
+ for (int i = 0; i < this.kernings.Count; i++)
+ {
+ KerningPair kerningPair = this.kernings[i];
+ Dictionary<int, float> dictionary;
+ if (target.kernings.TryGetValue((int)kerningPair.First, out dictionary))
+ {
+ float num;
+ if (dictionary.TryGetValue((int)kerningPair.Second, out num))
+ {
+ dictionary[(int)kerningPair.Second] = num + (float)kerningPair.Pixels;
+ }
+ else
+ {
+ dictionary[(int)kerningPair.Second] = (float)kerningPair.Pixels;
+ }
+ }
+ else
+ {
+ Dictionary<int, float> dictionary2 = new Dictionary<int, float>();
+ dictionary2[(int)kerningPair.Second] = (float)kerningPair.Pixels;
+ target.kernings[(int)kerningPair.First] = dictionary2;
+ }
+ }
+ }
+
+ public void AdjustOffsets(FontData target)
+ {
+ for (int i = 0; i < this.Offsets.Count; i++)
+ {
+ OffsetAdjustment offsetAdjustment = this.Offsets[i];
+ int index;
+ if (target.charMap.TryGetValue((int)offsetAdjustment.Char, out index))
+ {
+ Vector3 value = target.offsets[index];
+ value.x += (float)offsetAdjustment.OffsetX;
+ value.y += (float)offsetAdjustment.OffsetY;
+ target.offsets[index] = value;
+ }
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/FontLoader.cs b/Client/Assembly-CSharp/FontLoader.cs
new file mode 100644
index 0000000..c65a693
--- /dev/null
+++ b/Client/Assembly-CSharp/FontLoader.cs
@@ -0,0 +1,106 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using UnityEngine;
+
+public static class FontLoader
+{
+ public static FontData FromBinary(TextAsset dataSrc, FontExtensionData eData)
+ {
+ FontData fontData = new FontData();
+ using (MemoryStream memoryStream = new MemoryStream(dataSrc.bytes))
+ {
+ using (BinaryReader binaryReader = new BinaryReader(memoryStream))
+ {
+ if (memoryStream.ReadByte() != 66 || memoryStream.ReadByte() != 77 || memoryStream.ReadByte() != 70 || memoryStream.ReadByte() != 3)
+ {
+ throw new InvalidDataException("Wrong format font.");
+ }
+ long num = -1L;
+ while (memoryStream.Position < memoryStream.Length)
+ {
+ if (num == memoryStream.Position)
+ {
+ throw new InvalidDataException("Bad font.");
+ }
+ num = memoryStream.Position;
+ byte b = binaryReader.ReadByte();
+ int num2 = binaryReader.ReadInt32();
+ long position = memoryStream.Position;
+ switch (b)
+ {
+ default:
+ memoryStream.Position += (long)num2;
+ break;
+ case 2:
+ fontData.LineHeight = (float)binaryReader.ReadUInt16();
+ memoryStream.Position += 2L;
+ fontData.TextureSize = new Vector2((float)binaryReader.ReadUInt16(), (float)binaryReader.ReadUInt16());
+ memoryStream.Position = position + (long)num2;
+ break;
+ case 4:
+ {
+ int num3 = num2 / 20;
+ fontData.charMap = new Dictionary<int, int>(num3);
+ fontData.bounds.Capacity = num3;
+ fontData.offsets.Capacity = num3;
+ fontData.Channels.Capacity = num3;
+ fontData.kernings = new Dictionary<int, Dictionary<int, float>>(256);
+ for (int i = 0; i < num3; i++)
+ {
+ int key = binaryReader.ReadInt32();
+ int num4 = (int)binaryReader.ReadUInt16();
+ int num5 = (int)binaryReader.ReadUInt16();
+ int num6 = (int)binaryReader.ReadUInt16();
+ int num7 = (int)binaryReader.ReadUInt16();
+ int num8 = (int)binaryReader.ReadInt16();
+ int num9 = (int)binaryReader.ReadInt16();
+ int num10 = (int)binaryReader.ReadInt16();
+ binaryReader.ReadByte();
+ int input = (int)binaryReader.ReadByte();
+ fontData.charMap.Add(key, fontData.bounds.Count);
+ fontData.bounds.Add(new Vector4((float)num4, (float)num5, (float)num6, (float)num7));
+ fontData.offsets.Add(new Vector3((float)num8, (float)num9, (float)num10));
+ fontData.Channels.Add(FontLoader.IntToChannels(input));
+ }
+ break;
+ }
+ case 5:
+ while (memoryStream.Position < position + (long)num2)
+ {
+ int key2 = binaryReader.ReadInt32();
+ int key3 = binaryReader.ReadInt32();
+ int num11 = (int)binaryReader.ReadInt16();
+ Dictionary<int, float> dictionary;
+ if (!fontData.kernings.TryGetValue(key2, out dictionary))
+ {
+ fontData.kernings.Add(key2, dictionary = new Dictionary<int, float>(256));
+ }
+ dictionary.Add(key3, (float)num11);
+ }
+ break;
+ }
+ }
+ }
+ }
+ if (eData != null)
+ {
+ eData.AdjustKernings(fontData);
+ eData.AdjustOffsets(fontData);
+ }
+ return fontData;
+ }
+
+ private static Vector4 IntToChannels(int input)
+ {
+ Vector4 result = default(Vector4);
+ for (int i = 0; i < 4; i++)
+ {
+ if ((input >> i & 1) == 1)
+ {
+ result[i] = 1f;
+ }
+ }
+ return result;
+ }
+}
diff --git a/Client/Assembly-CSharp/GameData.cs b/Client/Assembly-CSharp/GameData.cs
new file mode 100644
index 0000000..4941bd6
--- /dev/null
+++ b/Client/Assembly-CSharp/GameData.cs
@@ -0,0 +1,556 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Assets.CoreScripts;
+using Hazel;
+using InnerNet;
+using UnityEngine;
+
+public class GameData : InnerNetObject, IDisconnectHandler
+{
+ public int PlayerCount
+ {
+ get
+ {
+ return this.AllPlayers.Count;
+ }
+ }
+
+ public static GameData Instance;
+
+ // 所有角色数据
+ public List<GameData.PlayerInfo> AllPlayers = new List<GameData.PlayerInfo>();
+
+ public int TotalTasks;
+
+ public int CompletedTasks;
+
+ public const byte InvalidPlayerId = 255;
+
+ public const byte DisconnectedPlayerId = 254;
+
+ public class TaskInfo
+ {
+ public uint Id;
+
+ public bool Complete;
+
+ public void Serialize(MessageWriter writer)
+ {
+ writer.WritePacked(this.Id);
+ writer.Write(this.Complete);
+ }
+
+ public void Deserialize(MessageReader reader)
+ {
+ this.Id = reader.ReadPackedUInt32();
+ this.Complete = reader.ReadBoolean();
+ }
+ }
+
+ //c 角色数据,包括外观、装饰、是否是imposter、是否死亡
+ public class PlayerInfo
+ {
+ public PlayerControl Object
+ {
+ get
+ {
+ if (!this._object)
+ {
+ this._object = PlayerControl.AllPlayerControls.FirstOrDefault((PlayerControl p) => p.PlayerId == this.PlayerId);
+ }
+ return this._object;
+ }
+ }
+
+ public readonly byte PlayerId;
+
+ public string PlayerName = string.Empty;
+
+ public byte ColorId;
+
+ public uint HatId;
+
+ public uint PetId;
+
+ public uint SkinId;
+
+ public bool Disconnected;
+
+ public List<GameData.TaskInfo> Tasks;
+
+ public bool IsImpostor;
+
+ public bool IsDead;
+
+ private PlayerControl _object;
+
+ public PlayerInfo(byte playerId)
+ {
+ this.PlayerId = playerId;
+ }
+
+ public PlayerInfo(PlayerControl pc) : this(pc.PlayerId)
+ {
+ this._object = pc;
+ }
+
+ public void Serialize(MessageWriter writer)
+ {
+ writer.Write(this.PlayerName);
+ writer.Write(this.ColorId);
+ writer.WritePacked(this.HatId);
+ writer.WritePacked(this.PetId);
+ writer.WritePacked(this.SkinId);
+ byte b = 0;
+ if (this.Disconnected)
+ {
+ b |= 1;
+ }
+ if (this.IsImpostor)
+ {
+ b |= 2;
+ }
+ if (this.IsDead)
+ {
+ b |= 4;
+ }
+ writer.Write(b);
+ if (this.Tasks != null)
+ {
+ writer.Write((byte)this.Tasks.Count);
+ for (int i = 0; i < this.Tasks.Count; i++)
+ {
+ this.Tasks[i].Serialize(writer);
+ }
+ return;
+ }
+ writer.Write(0);
+ }
+
+ public void Deserialize(MessageReader reader)
+ {
+ this.PlayerName = reader.ReadString();
+ this.ColorId = reader.ReadByte();
+ this.HatId = reader.ReadPackedUInt32();
+ this.PetId = reader.ReadPackedUInt32();
+ this.SkinId = reader.ReadPackedUInt32();
+ byte b = reader.ReadByte();
+ this.Disconnected = ((b & 1) > 0);
+ this.IsImpostor = ((b & 2) > 0);
+ this.IsDead = ((b & 4) > 0);
+ byte b2 = reader.ReadByte();
+ this.Tasks = new List<GameData.TaskInfo>((int)b2);
+ for (int i = 0; i < (int)b2; i++)
+ {
+ this.Tasks.Add(new GameData.TaskInfo());
+ this.Tasks[i].Deserialize(reader);
+ }
+ }
+
+ public GameData.TaskInfo FindTaskById(uint taskId)
+ {
+ for (int i = 0; i < this.Tasks.Count; i++)
+ {
+ if (this.Tasks[i].Id == taskId)
+ {
+ return this.Tasks[i];
+ }
+ }
+ return null;
+ }
+ }
+
+ private enum RpcCalls
+ {
+ SetTasks
+ }
+
+ public void Awake()
+ {
+ if (GameData.Instance && GameData.Instance != this)
+ {
+ UnityEngine.Object.Destroy(base.gameObject);
+ return;
+ }
+ GameData.Instance = this;
+ if (AmongUsClient.Instance)
+ {
+ AmongUsClient.Instance.DisconnectHandlers.AddUnique(this);
+ }
+ }
+
+ internal void SetDirty()
+ {
+ base.SetDirtyBit(uint.MaxValue);
+ }
+
+ public GameData.PlayerInfo GetHost()
+ {
+ ClientData host = AmongUsClient.Instance.GetHost();
+ if (host != null && host.Character)
+ {
+ return host.Character.Data;
+ }
+ return null;
+ }
+
+ public sbyte GetAvailableId()
+ {
+ sbyte i;
+ sbyte j;
+ for (i = 0; i < 10; i = j + 1)
+ {
+ if (!this.AllPlayers.Any((GameData.PlayerInfo p) => p.PlayerId == (byte)i))
+ {
+ return i;
+ }
+ j = i;
+ }
+ return -1;
+ }
+
+ public GameData.PlayerInfo GetPlayerById(byte id)
+ {
+ if (id == 255)
+ {
+ return null;
+ }
+ for (int i = 0; i < this.AllPlayers.Count; i++)
+ {
+ if (this.AllPlayers[i].PlayerId == id)
+ {
+ return this.AllPlayers[i];
+ }
+ }
+ return null;
+ }
+
+ public void UpdateName(byte playerId, string name)
+ {
+ GameData.PlayerInfo playerById = this.GetPlayerById(playerId);
+ if (playerById != null)
+ {
+ playerById.PlayerName = name;
+ }
+ base.SetDirtyBit(1U << (int)playerId);
+ }
+
+ public void UpdateColor(byte playerId, byte color)
+ {
+ GameData.PlayerInfo playerById = this.GetPlayerById(playerId);
+ if (playerById != null)
+ {
+ playerById.ColorId = color;
+ }
+ base.SetDirtyBit(1U << (int)playerId);
+ }
+
+ public void UpdateHat(byte playerId, uint hat)
+ {
+ GameData.PlayerInfo playerById = this.GetPlayerById(playerId);
+ if (playerById != null)
+ {
+ playerById.HatId = hat;
+ }
+ base.SetDirtyBit(1U << (int)playerId);
+ }
+
+ public void UpdatePet(byte playerId, uint petId)
+ {
+ GameData.PlayerInfo playerById = this.GetPlayerById(playerId);
+ if (playerById != null)
+ {
+ playerById.PetId = petId;
+ }
+ base.SetDirtyBit(1U << (int)playerId);
+ }
+
+ public void UpdateSkin(byte playerId, uint skin)
+ {
+ GameData.PlayerInfo playerById = this.GetPlayerById(playerId);
+ if (playerById != null)
+ {
+ playerById.SkinId = skin;
+ }
+ base.SetDirtyBit(1U << (int)playerId);
+ }
+
+ public void AddPlayer(PlayerControl pc)
+ {
+ GameData.PlayerInfo item = new GameData.PlayerInfo(pc);
+ this.AllPlayers.Add(item);
+ base.SetDirtyBit(1U << (int)pc.PlayerId);
+ }
+
+ public bool RemovePlayer(byte playerId)
+ {
+ for (int i = 0; i < this.AllPlayers.Count; i++)
+ {
+ if (this.AllPlayers[i].PlayerId == playerId)
+ {
+ this.SetDirty();
+ this.AllPlayers.RemoveAt(i);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void RecomputeTaskCounts()
+ {
+ this.TotalTasks = 0;
+ this.CompletedTasks = 0;
+ for (int i = 0; i < this.AllPlayers.Count; i++)
+ {
+ GameData.PlayerInfo playerInfo = this.AllPlayers[i];
+ if (!playerInfo.Disconnected && playerInfo.Tasks != null && playerInfo.Object && (PlayerControl.GameOptions.GhostsDoTasks || !playerInfo.IsDead) && !playerInfo.IsImpostor)
+ {
+ for (int j = 0; j < playerInfo.Tasks.Count; j++)
+ {
+ this.TotalTasks++;
+ if (playerInfo.Tasks[j].Complete)
+ {
+ this.CompletedTasks++;
+ }
+ }
+ }
+ }
+ }
+
+ public void TutOnlyRemoveTask(byte playerId, uint taskId)
+ {
+ GameData.PlayerInfo playerById = this.GetPlayerById(playerId);
+ GameData.TaskInfo item = playerById.FindTaskById(taskId);
+ playerById.Tasks.Remove(item);
+ this.RecomputeTaskCounts();
+ }
+
+ public void TutOnlyAddTask(byte playerId, uint taskId)
+ {
+ this.GetPlayerById(playerId).Tasks.Add(new GameData.TaskInfo
+ {
+ Id = taskId
+ });
+ this.TotalTasks++;
+ }
+
+ private void SetTasks(byte playerId, byte[] taskTypeIds)
+ {
+ GameData.PlayerInfo playerById = this.GetPlayerById(playerId);
+ if (playerById == null)
+ {
+ Debug.Log("Could not set tasks for player id: " + playerId);
+ return;
+ }
+ if (playerById.Disconnected)
+ {
+ return;
+ }
+ if (!playerById.Object)
+ {
+ Debug.Log(string.Concat(new object[]
+ {
+ "Could not set tasks for player (",
+ playerById.PlayerName,
+ "): ",
+ playerId
+ }));
+ return;
+ }
+ playerById.Tasks = new List<GameData.TaskInfo>(taskTypeIds.Length);
+ for (int i = 0; i < taskTypeIds.Length; i++)
+ {
+ playerById.Tasks.Add(new GameData.TaskInfo());
+ playerById.Tasks[i].Id = (uint)i;
+ }
+ playerById.Object.SetTasks(taskTypeIds);
+ base.SetDirtyBit(1U << (int)playerById.PlayerId);
+ }
+
+ public void CompleteTask(PlayerControl pc, uint taskId)
+ {
+ GameData.TaskInfo taskInfo = pc.Data.FindTaskById(taskId);
+ if (taskInfo == null)
+ {
+ Debug.LogWarning("Couldn't find task: " + taskId);
+ return;
+ }
+ if (!taskInfo.Complete)
+ {
+ taskInfo.Complete = true;
+ this.CompletedTasks++;
+ return;
+ }
+ Debug.LogWarning("Double complete task: " + taskId);
+ }
+
+ public void HandleDisconnect(PlayerControl player, DisconnectReasons reason)
+ {
+ if (!player)
+ {
+ return;
+ }
+ GameData.PlayerInfo playerById = this.GetPlayerById(player.PlayerId);
+ if (playerById == null)
+ {
+ return;
+ }
+ if (AmongUsClient.Instance.IsGameStarted)
+ {
+ if (!playerById.Disconnected)
+ {
+ playerById.Disconnected = true;
+ TempData.LastDeathReason = DeathReason.Disconnect;
+ this.ShowNotification(playerById.PlayerName, reason);
+ }
+ }
+ else if (this.RemovePlayer(player.PlayerId))
+ {
+ this.ShowNotification(playerById.PlayerName, reason);
+ }
+ this.RecomputeTaskCounts();
+ }
+
+ private void ShowNotification(string playerName, DisconnectReasons reason)
+ {
+ if (string.IsNullOrEmpty(playerName))
+ {
+ return;
+ }
+ if (reason <= DisconnectReasons.Banned)
+ {
+ if (reason == DisconnectReasons.ExitGame)
+ {
+ DestroyableSingleton<HudManager>.Instance.Notifier.AddItem(playerName + " left the game.");
+ return;
+ }
+ if (reason == DisconnectReasons.Banned)
+ {
+ GameData.PlayerInfo data = AmongUsClient.Instance.GetHost().Character.Data;
+ DestroyableSingleton<HudManager>.Instance.Notifier.AddItem(playerName + " was banned by " + data.PlayerName + ".");
+ return;
+ }
+ }
+ else if (reason == DisconnectReasons.Kicked)
+ {
+ GameData.PlayerInfo data2 = AmongUsClient.Instance.GetHost().Character.Data;
+ DestroyableSingleton<HudManager>.Instance.Notifier.AddItem(playerName + " was kicked by " + data2.PlayerName + ".");
+ return;
+ }
+ DestroyableSingleton<HudManager>.Instance.Notifier.AddItem(playerName + " left the game due to error.");
+ }
+
+ public void HandleDisconnect()
+ {
+ if (!AmongUsClient.Instance.IsGameStarted)
+ {
+ for (int i = this.AllPlayers.Count - 1; i >= 0; i--)
+ {
+ if (!this.AllPlayers[i].Object)
+ {
+ this.AllPlayers.RemoveAt(i);
+ }
+ }
+ }
+ }
+
+ public override bool Serialize(MessageWriter writer, bool initialState)
+ {
+ if (initialState)
+ {
+ if (!DestroyableSingleton<Telemetry>.Instance.IsInitialized)
+ {
+ DestroyableSingleton<Telemetry>.Instance.Initialize();
+ }
+ writer.WriteBytesAndSize(DestroyableSingleton<Telemetry>.Instance.CurrentGuid.ToByteArray());
+ writer.WritePacked(this.AllPlayers.Count);
+ for (int i = 0; i < this.AllPlayers.Count; i++)
+ {
+ GameData.PlayerInfo playerInfo = this.AllPlayers[i];
+ writer.Write(playerInfo.PlayerId);
+ playerInfo.Serialize(writer);
+ }
+ }
+ else
+ {
+ int position = writer.Position;
+ byte b = 0;
+ writer.Write(b);
+ for (int j = 0; j < this.AllPlayers.Count; j++)
+ {
+ GameData.PlayerInfo playerInfo2 = this.AllPlayers[j];
+ if ((this.DirtyBits & 1U << (int)playerInfo2.PlayerId) != 0U)
+ {
+ writer.Write(playerInfo2.PlayerId);
+ playerInfo2.Serialize(writer);
+ b += 1;
+ }
+ }
+ writer.Position = position;
+ writer.Write(b);
+ writer.Position = writer.Length;
+ this.DirtyBits = 0U;
+ }
+ return true;
+ }
+
+ public override void Deserialize(MessageReader reader, bool initialState)
+ {
+ if (initialState)
+ {
+ Guid gameGuid = new Guid(reader.ReadBytesAndSize());
+ if (!DestroyableSingleton<Telemetry>.Instance.IsInitialized)
+ {
+ DestroyableSingleton<Telemetry>.Instance.Initialize(gameGuid);
+ }
+ int num = reader.ReadPackedInt32();
+ for (int i = 0; i < num; i++)
+ {
+ GameData.PlayerInfo playerInfo = new GameData.PlayerInfo(reader.ReadByte());
+ playerInfo.Deserialize(reader);
+ this.AllPlayers.Add(playerInfo);
+ }
+ }
+ else
+ {
+ byte b = reader.ReadByte();
+ for (int j = 0; j < (int)b; j++)
+ {
+ byte b2 = reader.ReadByte();
+ GameData.PlayerInfo playerInfo2 = this.GetPlayerById(b2);
+ if (playerInfo2 != null)
+ {
+ playerInfo2.Deserialize(reader);
+ }
+ else
+ {
+ playerInfo2 = new GameData.PlayerInfo(b2);
+ playerInfo2.Deserialize(reader);
+ this.AllPlayers.Add(playerInfo2);
+ }
+ }
+ }
+ this.RecomputeTaskCounts();
+ }
+
+ public void RpcSetTasks(byte playerId, byte[] taskTypeIds)
+ {
+ if (AmongUsClient.Instance.AmClient)
+ {
+ this.SetTasks(playerId, taskTypeIds);
+ }
+ MessageWriter messageWriter = AmongUsClient.Instance.StartRpc(this.NetId, 0, SendOption.Reliable);
+ messageWriter.Write(playerId);
+ messageWriter.WriteBytesAndSize(taskTypeIds);
+ messageWriter.EndMessage();
+ }
+
+ public override void HandleRpc(byte callId, MessageReader reader)
+ {
+ if (callId == 0)
+ {
+ this.SetTasks(reader.ReadByte(), reader.ReadBytesAndSize());
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/GameDiscovery.cs b/Client/Assembly-CSharp/GameDiscovery.cs
new file mode 100644
index 0000000..5742e43
--- /dev/null
+++ b/Client/Assembly-CSharp/GameDiscovery.cs
@@ -0,0 +1,83 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Hazel.Udp;
+using InnerNet;
+using UnityEngine;
+
+public class GameDiscovery : MonoBehaviour
+{
+ public JoinGameButton ButtonPrefab;
+
+ public Transform ItemLocation;
+
+ public float YStart = 0.56f;
+
+ public float YOffset = -0.75f;
+
+ private Dictionary<string, JoinGameButton> received = new Dictionary<string, JoinGameButton>();
+
+ public void Start()
+ {
+ InnerDiscover component = base.GetComponent<InnerDiscover>();
+ component.OnPacketGet += this.Receive;
+ component.StartAsClient();
+ }
+
+ public void Update()
+ {
+ float time = Time.time;
+ string[] array = this.received.Keys.ToArray<string>();
+ int num = 0;
+ foreach (string key in array)
+ {
+ JoinGameButton joinGameButton = this.received[key];
+ if (time - joinGameButton.timeRecieved > 3f)
+ {
+ this.received.Remove(key);
+ UnityEngine.Object.Destroy(joinGameButton.gameObject);
+ }
+ else
+ {
+ joinGameButton.transform.localPosition = new Vector3(0f, this.YStart + (float)num * this.YOffset, -1f);
+ num++;
+ }
+ }
+ }
+
+ private void Receive(BroadcastPacket packet)
+ {
+ string[] array = packet.Data.Split(new char[]
+ {
+ '~'
+ });
+ string address = packet.GetAddress();
+ JoinGameButton joinGameButton;
+ if (this.received.TryGetValue(address, out joinGameButton))
+ {
+ joinGameButton.timeRecieved = Time.time;
+ joinGameButton.SetGameName(array);
+ return;
+ }
+ if (array[1].Equals("Open"))
+ {
+ this.CreateButtonForAddess(address, array);
+ }
+ }
+
+ private void CreateButtonForAddess(string fromAddress, string[] gameNameParts)
+ {
+ JoinGameButton joinGameButton;
+ if (this.received.TryGetValue(fromAddress, out joinGameButton))
+ {
+ UnityEngine.Object.Destroy(joinGameButton.gameObject);
+ }
+ JoinGameButton joinGameButton2 = UnityEngine.Object.Instantiate<JoinGameButton>(this.ButtonPrefab, this.ItemLocation);
+ joinGameButton2.transform.localPosition = new Vector3(0f, this.YStart + (float)(this.ItemLocation.childCount - 1) * this.YOffset, -1f);
+ joinGameButton2.netAddress = fromAddress;
+ joinGameButton2.timeRecieved = Time.time;
+ joinGameButton2.SetGameName(gameNameParts);
+ joinGameButton2.GetComponentInChildren<MeshRenderer>().material.SetInt("_Mask", 4);
+ this.received[fromAddress] = joinGameButton2;
+ }
+}
diff --git a/Client/Assembly-CSharp/GameModes.cs b/Client/Assembly-CSharp/GameModes.cs
new file mode 100644
index 0000000..67c0bac
--- /dev/null
+++ b/Client/Assembly-CSharp/GameModes.cs
@@ -0,0 +1,8 @@
+using System;
+
+public enum GameModes
+{
+ LocalGame,
+ OnlineGame,
+ FreePlay
+}
diff --git a/Client/Assembly-CSharp/GameObjectExtensions.cs b/Client/Assembly-CSharp/GameObjectExtensions.cs
new file mode 100644
index 0000000..57795eb
--- /dev/null
+++ b/Client/Assembly-CSharp/GameObjectExtensions.cs
@@ -0,0 +1,77 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public static class GameObjectExtensions
+{
+ public static T Find<T>(this List<T> self, GameObject toFind) where T : MonoBehaviour
+ {
+ for (int i = 0; i < self.Count; i++)
+ {
+ T t = self[i];
+ if (t.gameObject == toFind)
+ {
+ return t;
+ }
+ }
+ return default(T);
+ }
+
+ public static void SetZ(this Transform self, float z)
+ {
+ Vector3 localPosition = self.localPosition;
+ localPosition.z = z;
+ self.localPosition = localPosition;
+ }
+
+ public static void LookAt2d(this Transform self, Vector3 target)
+ {
+ Vector3 vector = target - self.transform.position;
+ vector.Normalize();
+ float num = Mathf.Atan2(vector.y, vector.x);
+ self.transform.rotation = Quaternion.Euler(0f, 0f, num * 57.29578f);
+ }
+
+ public static void LookAt2d(this Transform self, Transform target)
+ {
+ self.LookAt2d(target.transform.position);
+ }
+
+ public static void DestroyChildren(this Transform self)
+ {
+ for (int i = self.childCount - 1; i > -1; i--)
+ {
+ Transform child = self.GetChild(i);
+ child.transform.SetParent(null);
+ UnityEngine.Object.Destroy(child.gameObject);
+ }
+ }
+
+ public static void DestroyChildren(this MonoBehaviour self)
+ {
+ for (int i = self.transform.childCount - 1; i > -1; i--)
+ {
+ UnityEngine.Object.Destroy(self.transform.GetChild(i).gameObject);
+ }
+ }
+
+ public static void ForEachChild(this GameObject self, Action<GameObject> todo)
+ {
+ for (int i = self.transform.childCount - 1; i > -1; i--)
+ {
+ todo(self.transform.GetChild(i).gameObject);
+ }
+ }
+
+ public static void ForEachChildBehavior<T>(this MonoBehaviour self, Action<T> todo) where T : MonoBehaviour
+ {
+ for (int i = self.transform.childCount - 1; i > -1; i--)
+ {
+ T component = self.transform.GetChild(i).GetComponent<T>();
+ if (component)
+ {
+ todo(component);
+ }
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/GameOptionsData.cs b/Client/Assembly-CSharp/GameOptionsData.cs
new file mode 100644
index 0000000..b3ef55f
--- /dev/null
+++ b/Client/Assembly-CSharp/GameOptionsData.cs
@@ -0,0 +1,332 @@
+using System;
+using System.IO;
+using System.Text;
+using InnerNet;
+using UnityEngine;
+
+public class GameOptionsData : IBytesSerializable
+{
+ private const byte GameDataVersion = 1;
+
+ public static readonly string[] MapNames = new string[]
+ {
+ "The Skeld",
+ "???",
+ "???"
+ };
+
+ public static readonly float[] KillDistances = new float[]
+ {
+ 1f,
+ 1.8f,
+ 2.5f
+ };
+
+ public static readonly string[] KillDistanceStrings = new string[]
+ {
+ "Short",
+ "Normal",
+ "Long"
+ };
+
+ public int MaxPlayers = 10;
+
+ public GameKeywords Keywords = GameKeywords.English;
+
+ public byte MapId;
+
+ public float PlayerSpeedMod = 1f;
+
+ public float CrewLightMod = 1f;
+
+ public float ImpostorLightMod = 1.5f;
+
+ public float KillCooldown = 15f;
+
+ public int NumCommonTasks = 1;
+
+ public int NumLongTasks = 1;
+
+ public int NumShortTasks = 2;
+
+ public int NumEmergencyMeetings = 1;
+
+ public int EmergencyCooldown = 15;
+
+ public int NumImpostors = 1;
+
+ public bool GhostsDoTasks = true;
+
+ public int KillDistance = 1;
+
+ public int DiscussionTime = 15;
+
+ public int VotingTime = 120;
+
+ public bool isDefaults = true;
+
+ private static readonly int[] RecommendedKillCooldown = new int[]
+ {
+ 0,
+ 0,
+ 0,
+ 0,
+ 45,
+ 30,
+ 15,
+ 35,
+ 30,
+ 25,
+ 20
+ };
+
+ private static readonly int[] RecommendedImpostors = new int[]
+ {
+ 0,
+ 0,
+ 0,
+ 0,
+ 1,
+ 1,
+ 1,
+ 2,
+ 2,
+ 2,
+ 2
+ };
+
+ private static readonly int[] MaxImpostors = new int[]
+ {
+ 0,
+ 0,
+ 0,
+ 0,
+ 1,
+ 1,
+ 1,
+ 2,
+ 2,
+ 3,
+ 3
+ };
+
+ public static readonly int[] MinPlayers = new int[]
+ {
+ 4,
+ 4,
+ 7,
+ 9
+ };
+
+ public void ToggleMapFilter(byte newId)
+ {
+ byte b = (byte)(((int)this.MapId ^ 1 << (int)newId) & 3);
+ if (b != 0)
+ {
+ this.MapId = b;
+ }
+ }
+
+ public bool FilterContainsMap(byte newId)
+ {
+ int num = 1 << (int)newId;
+ return ((int)this.MapId & num) == num;
+ }
+
+ public GameOptionsData()
+ {
+ try
+ {
+ SystemLanguage systemLanguage = Application.systemLanguage;
+ if (systemLanguage <= SystemLanguage.Portuguese)
+ {
+ if (systemLanguage != SystemLanguage.Korean)
+ {
+ if (systemLanguage == SystemLanguage.Portuguese)
+ {
+ this.Keywords = GameKeywords.Portuguese;
+ }
+ }
+ else
+ {
+ this.Keywords = GameKeywords.Korean;
+ }
+ }
+ else if (systemLanguage != SystemLanguage.Russian)
+ {
+ if (systemLanguage == SystemLanguage.Spanish)
+ {
+ this.Keywords = GameKeywords.Spanish;
+ }
+ }
+ else
+ {
+ this.Keywords = GameKeywords.Russian;
+ }
+ }
+ catch
+ {
+ }
+ }
+
+ public void SetRecommendations(int numPlayers, GameModes modes)
+ {
+ numPlayers = Mathf.Clamp(numPlayers, 4, 10);
+ this.PlayerSpeedMod = 1f;
+ this.CrewLightMod = 1f;
+ this.ImpostorLightMod = 1.5f;
+ this.KillCooldown = (float)GameOptionsData.RecommendedKillCooldown[numPlayers];
+ this.NumCommonTasks = 1;
+ this.NumLongTasks = 1;
+ this.NumShortTasks = 2;
+ this.NumEmergencyMeetings = 1;
+ if (modes != GameModes.OnlineGame)
+ {
+ this.NumImpostors = GameOptionsData.RecommendedImpostors[numPlayers];
+ }
+ this.KillDistance = 1;
+ this.DiscussionTime = 15;
+ this.VotingTime = 120;
+ this.isDefaults = true;
+ this.EmergencyCooldown = ((modes == GameModes.OnlineGame) ? 15 : 0);
+ }
+
+ public void Serialize(BinaryWriter writer)
+ {
+ writer.Write(1);
+ writer.Write((byte)this.MaxPlayers);
+ writer.Write((uint)this.Keywords);
+ writer.Write(this.MapId);
+ writer.Write(this.PlayerSpeedMod);
+ writer.Write(this.CrewLightMod);
+ writer.Write(this.ImpostorLightMod);
+ writer.Write(this.KillCooldown);
+ writer.Write((byte)this.NumCommonTasks);
+ writer.Write((byte)this.NumLongTasks);
+ writer.Write((byte)this.NumShortTasks);
+ writer.Write(this.NumEmergencyMeetings);
+ writer.Write((byte)this.NumImpostors);
+ writer.Write((byte)this.KillDistance);
+ writer.Write(this.DiscussionTime);
+ writer.Write(this.VotingTime);
+ writer.Write(this.isDefaults);
+ writer.Write((byte)this.EmergencyCooldown);
+ }
+
+ public static GameOptionsData Deserialize(BinaryReader reader)
+ {
+ try
+ {
+ byte b = reader.ReadByte();
+ if (b != 1 && b != 2)
+ {
+ return null;
+ }
+ GameOptionsData gameOptionsData = new GameOptionsData();
+ gameOptionsData.MaxPlayers = (int)reader.ReadByte();
+ gameOptionsData.Keywords = (GameKeywords)reader.ReadUInt32();
+ gameOptionsData.MapId = reader.ReadByte();
+ gameOptionsData.PlayerSpeedMod = reader.ReadSingle();
+ gameOptionsData.CrewLightMod = reader.ReadSingle();
+ gameOptionsData.ImpostorLightMod = reader.ReadSingle();
+ gameOptionsData.KillCooldown = reader.ReadSingle();
+ gameOptionsData.NumCommonTasks = (int)reader.ReadByte();
+ gameOptionsData.NumLongTasks = (int)reader.ReadByte();
+ gameOptionsData.NumShortTasks = (int)reader.ReadByte();
+ gameOptionsData.NumEmergencyMeetings = reader.ReadInt32();
+ gameOptionsData.NumImpostors = (int)reader.ReadByte();
+ gameOptionsData.KillDistance = (int)reader.ReadByte();
+ gameOptionsData.DiscussionTime = reader.ReadInt32();
+ gameOptionsData.VotingTime = reader.ReadInt32();
+ gameOptionsData.isDefaults = reader.ReadBoolean();
+ try
+ {
+ gameOptionsData.EmergencyCooldown = (int)reader.ReadByte();
+ }
+ catch
+ {
+ }
+ return gameOptionsData;
+ }
+ catch
+ {
+ }
+ return null;
+ }
+
+ public byte[] ToBytes()
+ {
+ byte[] result;
+ using (MemoryStream memoryStream = new MemoryStream())
+ {
+ using (BinaryWriter binaryWriter = new BinaryWriter(memoryStream))
+ {
+ this.Serialize(binaryWriter);
+ binaryWriter.Flush();
+ memoryStream.Position = 0L;
+ result = memoryStream.ToArray();
+ }
+ }
+ return result;
+ }
+
+ public static GameOptionsData FromBytes(byte[] bytes)
+ {
+ GameOptionsData result;
+ using (MemoryStream memoryStream = new MemoryStream(bytes))
+ {
+ using (BinaryReader binaryReader = new BinaryReader(memoryStream))
+ {
+ result = (GameOptionsData.Deserialize(binaryReader) ?? new GameOptionsData());
+ }
+ }
+ return result;
+ }
+
+ public override string ToString()
+ {
+ return this.ToHudString(10);
+ }
+
+ public string ToHudString(int numPlayers)
+ {
+ numPlayers = Mathf.Clamp(numPlayers, 0, 10);
+ StringBuilder stringBuilder = new StringBuilder(256);
+ stringBuilder.AppendLine(DestroyableSingleton<TranslationController>.Instance.GetString(this.isDefaults ? StringNames.GameRecommendedSettings : StringNames.GameCustomSettings, Array.Empty<object>()));
+ int num = GameOptionsData.MaxImpostors[numPlayers];
+ stringBuilder.AppendLine(DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.GameMapName, Array.Empty<object>()) + ": " + GameOptionsData.MapNames[(int)this.MapId]);
+ stringBuilder.Append(string.Format("{0}: {1}", DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.GameNumImpostors, Array.Empty<object>()), this.NumImpostors));
+ if (this.NumImpostors > num)
+ {
+ stringBuilder.Append(string.Format(" ({0}: {1})", DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.Limit, Array.Empty<object>()), num));
+ }
+ stringBuilder.AppendLine();
+ stringBuilder.AppendLine(string.Format("{0}: {1}", DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.GameNumMeetings, Array.Empty<object>()), this.NumEmergencyMeetings));
+ stringBuilder.AppendLine(string.Format("{0}: {1}s", DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.GameEmergencyCooldown, Array.Empty<object>()), this.EmergencyCooldown));
+ stringBuilder.AppendLine(string.Format("Discussion Time: {0}s", this.DiscussionTime));
+ if (this.VotingTime > 0)
+ {
+ stringBuilder.AppendLine(string.Format("{0}: {1}s", DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.GameVotingTime, Array.Empty<object>()), this.VotingTime));
+ }
+ else
+ {
+ stringBuilder.AppendLine(DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.GameVotingTime, Array.Empty<object>()) + ": ∞s");
+ }
+ stringBuilder.AppendLine(string.Format("{0}: {1}x", DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.GamePlayerSpeed, Array.Empty<object>()), this.PlayerSpeedMod));
+ stringBuilder.AppendLine(string.Format("{0}: {1}x", DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.GameCrewLight, Array.Empty<object>()), this.CrewLightMod));
+ stringBuilder.AppendLine(string.Format("{0}: {1}x", DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.GameImpostorLight, Array.Empty<object>()), this.ImpostorLightMod));
+ stringBuilder.AppendLine(string.Format("{0}: {1}s", DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.GameKillCooldown, Array.Empty<object>()), this.KillCooldown));
+ stringBuilder.AppendLine(DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.GameKillDistance, Array.Empty<object>()) + ": " + GameOptionsData.KillDistanceStrings[this.KillDistance]);
+ stringBuilder.AppendLine(string.Format("{0}: {1}", DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.GameCommonTasks, Array.Empty<object>()), this.NumCommonTasks));
+ stringBuilder.AppendLine(string.Format("{0}: {1}", DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.GameLongTasks, Array.Empty<object>()), this.NumLongTasks));
+ stringBuilder.Append(string.Format("{0}: {1}", DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.GameShortTasks, Array.Empty<object>()), this.NumShortTasks));
+ return stringBuilder.ToString();
+ }
+
+ public int GetAdjustedNumImpostors(int playerCount)
+ {
+ int numImpostors = PlayerControl.GameOptions.NumImpostors;
+ int max = GameOptionsData.MaxImpostors[GameData.Instance.PlayerCount];
+ return Mathf.Clamp(numImpostors, 1, max);
+ }
+}
diff --git a/Client/Assembly-CSharp/GameOptionsMenu.cs b/Client/Assembly-CSharp/GameOptionsMenu.cs
new file mode 100644
index 0000000..1c44375
--- /dev/null
+++ b/Client/Assembly-CSharp/GameOptionsMenu.cs
@@ -0,0 +1,133 @@
+using System;
+using UnityEngine;
+
+public class GameOptionsMenu : MonoBehaviour
+{
+ private GameOptionsData cachedData;
+
+ public GameObject ResetButton;
+
+ private OptionBehaviour[] Children;
+
+ public void Start()
+ {
+ this.Children = base.GetComponentsInChildren<OptionBehaviour>();
+ this.cachedData = PlayerControl.GameOptions;
+ for (int i = 0; i < this.Children.Length; i++)
+ {
+ OptionBehaviour optionBehaviour = this.Children[i];
+ optionBehaviour.OnValueChanged = new Action<OptionBehaviour>(this.ValueChanged);
+ if (AmongUsClient.Instance && !AmongUsClient.Instance.AmHost)
+ {
+ optionBehaviour.SetAsPlayer();
+ }
+ }
+ }
+
+ public void Update()
+ {
+ if (this.cachedData != PlayerControl.GameOptions)
+ {
+ this.cachedData = PlayerControl.GameOptions;
+ this.RefreshChildren();
+ }
+ }
+
+ private void RefreshChildren()
+ {
+ for (int i = 0; i < this.Children.Length; i++)
+ {
+ OptionBehaviour optionBehaviour = this.Children[i];
+ optionBehaviour.enabled = false;
+ optionBehaviour.enabled = true;
+ }
+ }
+
+ public void ValueChanged(OptionBehaviour option)
+ {
+ if (!AmongUsClient.Instance || !AmongUsClient.Instance.AmHost)
+ {
+ return;
+ }
+ if (option.Title == StringNames.GameRecommendedSettings)
+ {
+ if (this.cachedData.isDefaults)
+ {
+ this.cachedData.isDefaults = false;
+ }
+ else
+ {
+ this.cachedData.SetRecommendations(GameData.Instance.PlayerCount, AmongUsClient.Instance.GameMode);
+ }
+ this.RefreshChildren();
+ }
+ else
+ {
+ GameOptionsData gameOptions = PlayerControl.GameOptions;
+ StringNames title = option.Title;
+ switch (title)
+ {
+ case StringNames.GameMapName:
+ gameOptions.MapId = (byte)option.GetInt();
+ break;
+ case StringNames.GameNumImpostors:
+ gameOptions.NumImpostors = option.GetInt();
+ break;
+ case StringNames.GameNumMeetings:
+ gameOptions.NumEmergencyMeetings = option.GetInt();
+ break;
+ case StringNames.GameDiscussTime:
+ gameOptions.DiscussionTime = option.GetInt();
+ break;
+ case StringNames.GameVotingTime:
+ gameOptions.VotingTime = option.GetInt();
+ break;
+ case StringNames.GamePlayerSpeed:
+ gameOptions.PlayerSpeedMod = option.GetFloat();
+ break;
+ case StringNames.GameCrewLight:
+ gameOptions.CrewLightMod = option.GetFloat();
+ break;
+ case StringNames.GameImpostorLight:
+ gameOptions.ImpostorLightMod = option.GetFloat();
+ break;
+ case StringNames.GameKillCooldown:
+ gameOptions.KillCooldown = option.GetFloat();
+ break;
+ case StringNames.GameKillDistance:
+ gameOptions.KillDistance = option.GetInt();
+ break;
+ case StringNames.GameCommonTasks:
+ gameOptions.NumCommonTasks = option.GetInt();
+ break;
+ case StringNames.GameLongTasks:
+ gameOptions.NumLongTasks = option.GetInt();
+ break;
+ case StringNames.GameShortTasks:
+ gameOptions.NumShortTasks = option.GetInt();
+ break;
+ default:
+ if (title != StringNames.GameEmergencyCooldown)
+ {
+ Debug.Log("Ono, unrecognized setting: " + option.Title);
+ }
+ else
+ {
+ gameOptions.EmergencyCooldown = option.GetInt();
+ }
+ break;
+ }
+ if (gameOptions.isDefaults && option.Title != StringNames.GameMapName)
+ {
+ gameOptions.isDefaults = false;
+ this.RefreshChildren();
+ }
+ }
+ PlayerControl localPlayer = PlayerControl.LocalPlayer;
+ if (localPlayer == null)
+ {
+ return;
+ }
+ localPlayer.RpcSyncSettings(PlayerControl.GameOptions);
+ }
+}
diff --git a/Client/Assembly-CSharp/GameOverReason.cs b/Client/Assembly-CSharp/GameOverReason.cs
new file mode 100644
index 0000000..6f11220
--- /dev/null
+++ b/Client/Assembly-CSharp/GameOverReason.cs
@@ -0,0 +1,12 @@
+using System;
+
+public enum GameOverReason
+{
+ HumansByVote,
+ HumansByTask,
+ ImpostorByVote,
+ ImpostorByKill,
+ ImpostorBySabotage,
+ ImpostorDisconnect,
+ HumansDisconnect
+}
diff --git a/Client/Assembly-CSharp/GameSettingMenu.cs b/Client/Assembly-CSharp/GameSettingMenu.cs
new file mode 100644
index 0000000..d0d80dc
--- /dev/null
+++ b/Client/Assembly-CSharp/GameSettingMenu.cs
@@ -0,0 +1,37 @@
+using System;
+using UnityEngine;
+
+public class GameSettingMenu : MonoBehaviour
+{
+ public Transform[] AllItems;
+
+ public float YStart;
+
+ public float YOffset;
+
+ public Transform[] HideForOnline;
+
+ private void OnEnable()
+ {
+ int num = 0;
+ for (int i = 0; i < this.AllItems.Length; i++)
+ {
+ Transform transform = this.AllItems[i];
+ if (transform.gameObject.activeSelf)
+ {
+ if ((AmongUsClient.Instance.GameMode == GameModes.OnlineGame && this.HideForOnline.IndexOf(transform) != -1) || transform.name == "MapName")
+ {
+ transform.gameObject.SetActive(false);
+ }
+ else
+ {
+ Vector3 localPosition = transform.localPosition;
+ localPosition.y = this.YStart - (float)num * this.YOffset;
+ transform.localPosition = localPosition;
+ num++;
+ }
+ }
+ }
+ base.GetComponent<Scroller>().YBounds.max = (float)num * this.YOffset / 2f + 0.1f;
+ }
+}
diff --git a/Client/Assembly-CSharp/GameStartManager.cs b/Client/Assembly-CSharp/GameStartManager.cs
new file mode 100644
index 0000000..69f1967
--- /dev/null
+++ b/Client/Assembly-CSharp/GameStartManager.cs
@@ -0,0 +1,215 @@
+using System;
+using InnerNet;
+using UnityEngine;
+
+public class GameStartManager : DestroyableSingleton<GameStartManager>, IDisconnectHandler
+{
+ public int MinPlayers = 4;
+
+ public TextRenderer PlayerCounter;
+
+ private int LastPlayerCount = -1;
+
+ public GameObject GameSizePopup;
+
+ public TextRenderer GameRoomName;
+
+ public LobbyBehaviour LobbyPrefab;
+
+ public TextRenderer GameStartText;
+
+ public SpriteRenderer StartButton;
+
+ public SpriteRenderer MakePublicButton;
+
+ public Sprite PublicGameImage;
+
+ public Sprite PrivateGameImage;
+
+ private GameStartManager.StartingStates startState;
+
+ private float countDownTimer;
+
+ private enum StartingStates
+ {
+ NotStarting,
+ Countdown,
+ Starting
+ }
+
+ public void Start()
+ {
+ if (DestroyableSingleton<TutorialManager>.InstanceExists)
+ {
+ UnityEngine.Object.Destroy(base.gameObject);
+ return;
+ }
+ string text = InnerNetClient.IntToGameName(AmongUsClient.Instance.GameId);
+ if (text != null)
+ {
+ this.GameRoomName.Text = DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.RoomCode, Array.Empty<object>()) + "\r\n" + text;
+ }
+ else
+ {
+ this.StartButton.transform.localPosition = new Vector3(0f, -0.2f, 0f);
+ this.PlayerCounter.transform.localPosition = new Vector3(0f, -0.8f, 0f);
+ }
+ AmongUsClient.Instance.DisconnectHandlers.AddUnique(this);
+ if (!AmongUsClient.Instance.AmHost)
+ {
+ this.StartButton.gameObject.SetActive(false);
+ }
+ else
+ {
+ LobbyBehaviour.Instance = UnityEngine.Object.Instantiate<LobbyBehaviour>(this.LobbyPrefab);
+ AmongUsClient.Instance.Spawn(LobbyBehaviour.Instance, -2, SpawnFlags.None);
+ }
+ this.MakePublicButton.gameObject.SetActive(AmongUsClient.Instance.GameMode == GameModes.OnlineGame);
+ }
+
+ public void MakePublic()
+ {
+ if (AmongUsClient.Instance.AmHost)
+ {
+ AmongUsClient.Instance.ChangeGamePublic(!AmongUsClient.Instance.IsGamePublic);
+ }
+ }
+
+ public void Update()
+ {
+ if (!GameData.Instance)
+ {
+ return;
+ }
+ this.MakePublicButton.sprite = (AmongUsClient.Instance.IsGamePublic ? this.PublicGameImage : this.PrivateGameImage);
+ if (GameData.Instance.PlayerCount != this.LastPlayerCount)
+ {
+ this.LastPlayerCount = GameData.Instance.PlayerCount;
+ string arg = "[FF0000FF]";
+ if (this.LastPlayerCount > this.MinPlayers)
+ {
+ arg = "[00FF00FF]";
+ }
+ if (this.LastPlayerCount == this.MinPlayers)
+ {
+ arg = "[FFFF00FF]";
+ }
+ this.PlayerCounter.Text = string.Format("{0}{1}/{2}", arg, this.LastPlayerCount, PlayerControl.GameOptions.MaxPlayers);
+ this.StartButton.color = ((this.LastPlayerCount >= this.MinPlayers) ? Palette.EnabledColor : Palette.DisabledColor);
+ if (DestroyableSingleton<DiscordManager>.InstanceExists)
+ {
+ if (AmongUsClient.Instance.AmHost && AmongUsClient.Instance.GameMode == GameModes.OnlineGame)
+ {
+ DestroyableSingleton<DiscordManager>.Instance.SetInLobbyHost(this.LastPlayerCount, AmongUsClient.Instance.GameId);
+ }
+ else
+ {
+ DestroyableSingleton<DiscordManager>.Instance.SetInLobbyClient();
+ }
+ }
+ }
+ if (AmongUsClient.Instance.AmHost)
+ {
+ if (this.startState == GameStartManager.StartingStates.Countdown)
+ {
+ int num = Mathf.CeilToInt(this.countDownTimer);
+ this.countDownTimer -= Time.deltaTime;
+ int num2 = Mathf.CeilToInt(this.countDownTimer);
+ this.GameStartText.Text = string.Format("Starting in {0}", num2);
+ if (num != num2)
+ {
+ PlayerControl.LocalPlayer.RpcSetStartCounter(num2);
+ }
+ if (num2 <= 0)
+ {
+ this.FinallyBegin();
+ return;
+ }
+ }
+ else
+ {
+ this.GameStartText.Text = string.Empty;
+ }
+ }
+ }
+
+ public void ResetStartState()
+ {
+ this.startState = GameStartManager.StartingStates.NotStarting;
+ if (this.StartButton && this.StartButton.gameObject)
+ {
+ this.StartButton.gameObject.SetActive(AmongUsClient.Instance.AmHost);
+ }
+ PlayerControl.LocalPlayer.RpcSetStartCounter(-1);
+ }
+
+ public void SetStartCounter(sbyte sec)
+ {
+ if (sec == -1)
+ {
+ this.GameStartText.Text = string.Empty;
+ return;
+ }
+ this.GameStartText.Text = string.Format("Starting in {0}", sec);
+ }
+
+ public void BeginGame()
+ {
+ if (this.startState != GameStartManager.StartingStates.NotStarting)
+ {
+ return;
+ }
+ if (SaveManager.ShowMinPlayerWarning && GameData.Instance.PlayerCount == this.MinPlayers)
+ {
+ this.GameSizePopup.SetActive(true);
+ return;
+ }
+ if (GameData.Instance.PlayerCount < this.MinPlayers)
+ {
+ base.StartCoroutine(Effects.Shake(this.PlayerCounter.transform, 0.75f, 0.25f));
+ return;
+ }
+ this.ReallyBegin(false);
+ }
+
+ public void ReallyBegin(bool neverShow)
+ {
+ this.startState = GameStartManager.StartingStates.Countdown;
+ if (neverShow)
+ {
+ SaveManager.ShowMinPlayerWarning = false;
+ }
+ this.StartButton.gameObject.SetActive(false);
+ this.countDownTimer = 10.0001f;
+ this.startState = GameStartManager.StartingStates.Countdown;
+ }
+
+ public void FinallyBegin()
+ {
+ if (this.startState != GameStartManager.StartingStates.Countdown)
+ {
+ return;
+ }
+ this.startState = GameStartManager.StartingStates.Starting;
+ AmongUsClient.Instance.StartGame();
+ AmongUsClient.Instance.DisconnectHandlers.Remove(this);
+ UnityEngine.Object.Destroy(base.gameObject);
+ }
+
+ public void HandleDisconnect(PlayerControl pc, DisconnectReasons reason)
+ {
+ if (AmongUsClient.Instance.AmHost)
+ {
+ this.LastPlayerCount = -1;
+ if (this.StartButton)
+ {
+ this.StartButton.gameObject.SetActive(true);
+ }
+ }
+ }
+
+ public void HandleDisconnect()
+ {
+ this.HandleDisconnect(null, DisconnectReasons.ExitGame);
+ }
+}
diff --git a/Client/Assembly-CSharp/GarbageBehaviour.cs b/Client/Assembly-CSharp/GarbageBehaviour.cs
new file mode 100644
index 0000000..8fbc191
--- /dev/null
+++ b/Client/Assembly-CSharp/GarbageBehaviour.cs
@@ -0,0 +1,13 @@
+using System;
+using UnityEngine;
+
+public class GarbageBehaviour : MonoBehaviour
+{
+ public void FixedUpdate()
+ {
+ if (base.transform.localPosition.y < -3.49f)
+ {
+ UnityEngine.Object.Destroy(base.gameObject);
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/GoogleMobileAds/Api/AdErrorEventArgs.cs b/Client/Assembly-CSharp/GoogleMobileAds/Api/AdErrorEventArgs.cs
new file mode 100644
index 0000000..ab105d0
--- /dev/null
+++ b/Client/Assembly-CSharp/GoogleMobileAds/Api/AdErrorEventArgs.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace GoogleMobileAds.Api
+{
+ public class AdErrorEventArgs : EventArgs
+ {
+ public string Message { get; set; }
+ }
+}
diff --git a/Client/Assembly-CSharp/GoogleMobileAds/Api/AdFailedToLoadEventArgs.cs b/Client/Assembly-CSharp/GoogleMobileAds/Api/AdFailedToLoadEventArgs.cs
new file mode 100644
index 0000000..42389fc
--- /dev/null
+++ b/Client/Assembly-CSharp/GoogleMobileAds/Api/AdFailedToLoadEventArgs.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace GoogleMobileAds.Api
+{
+ public class AdFailedToLoadEventArgs : EventArgs
+ {
+ public string Message { get; set; }
+ }
+}
diff --git a/Client/Assembly-CSharp/GoogleMobileAds/Api/AdLoader.cs b/Client/Assembly-CSharp/GoogleMobileAds/Api/AdLoader.cs
new file mode 100644
index 0000000..3116a90
--- /dev/null
+++ b/Client/Assembly-CSharp/GoogleMobileAds/Api/AdLoader.cs
@@ -0,0 +1,93 @@
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using GoogleMobileAds.Common;
+
+namespace GoogleMobileAds.Api
+{
+ public class AdLoader
+ {
+ public Dictionary<string, Action<CustomNativeTemplateAd, string>> CustomNativeTemplateClickHandlers { get; private set; }
+
+ public string AdUnitId { get; private set; }
+
+ public HashSet<NativeAdType> AdTypes { get; private set; }
+
+ public HashSet<string> TemplateIds { get; private set; }
+
+ public event EventHandler<AdFailedToLoadEventArgs> OnAdFailedToLoad;
+
+ public event EventHandler<CustomNativeEventArgs> OnCustomNativeTemplateAdLoaded;
+
+ private IAdLoaderClient adLoaderClient;
+
+ public class Builder
+ {
+ internal string AdUnitId { get; private set; }
+
+ internal HashSet<NativeAdType> AdTypes { get; private set; }
+
+ internal HashSet<string> TemplateIds { get; private set; }
+
+ internal Dictionary<string, Action<CustomNativeTemplateAd, string>> CustomNativeTemplateClickHandlers { get; private set; }
+
+ public Builder(string adUnitId)
+ {
+ this.AdUnitId = adUnitId;
+ this.AdTypes = new HashSet<NativeAdType>();
+ this.TemplateIds = new HashSet<string>();
+ this.CustomNativeTemplateClickHandlers = new Dictionary<string, Action<CustomNativeTemplateAd, string>>();
+ }
+
+ public AdLoader.Builder ForCustomNativeAd(string templateId)
+ {
+ this.TemplateIds.Add(templateId);
+ this.AdTypes.Add(NativeAdType.CustomTemplate);
+ return this;
+ }
+
+ public AdLoader.Builder ForCustomNativeAd(string templateId, Action<CustomNativeTemplateAd, string> callback)
+ {
+ this.TemplateIds.Add(templateId);
+ this.CustomNativeTemplateClickHandlers[templateId] = callback;
+ this.AdTypes.Add(NativeAdType.CustomTemplate);
+ return this;
+ }
+
+ public AdLoader Build()
+ {
+ return new AdLoader(this);
+ }
+ }
+
+ private AdLoader(AdLoader.Builder builder)
+ {
+ this.AdUnitId = string.Copy(builder.AdUnitId);
+ this.CustomNativeTemplateClickHandlers = new Dictionary<string, Action<CustomNativeTemplateAd, string>>(builder.CustomNativeTemplateClickHandlers);
+ this.TemplateIds = new HashSet<string>(builder.TemplateIds);
+ this.AdTypes = new HashSet<NativeAdType>(builder.AdTypes);
+ MethodInfo method = Type.GetType("GoogleMobileAds.GoogleMobileAdsClientFactory,Assembly-CSharp").GetMethod("BuildAdLoaderClient", BindingFlags.Static | BindingFlags.Public);
+ this.adLoaderClient = (IAdLoaderClient)method.Invoke(null, new object[]
+ {
+ this
+ });
+ Utils.CheckInitialization();
+ this.adLoaderClient.OnCustomNativeTemplateAdLoaded += delegate(object sender, CustomNativeEventArgs args)
+ {
+ this.OnCustomNativeTemplateAdLoaded(this, args);
+ };
+ this.adLoaderClient.OnAdFailedToLoad += delegate(object sender, AdFailedToLoadEventArgs args)
+ {
+ if (this.OnAdFailedToLoad != null)
+ {
+ this.OnAdFailedToLoad(this, args);
+ }
+ };
+ }
+
+ public void LoadAd(AdRequest request)
+ {
+ this.adLoaderClient.LoadAd(request);
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/GoogleMobileAds/Api/AdPosition.cs b/Client/Assembly-CSharp/GoogleMobileAds/Api/AdPosition.cs
new file mode 100644
index 0000000..6bc2a49
--- /dev/null
+++ b/Client/Assembly-CSharp/GoogleMobileAds/Api/AdPosition.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace GoogleMobileAds.Api
+{
+ public enum AdPosition
+ {
+ Top,
+ Bottom,
+ TopLeft,
+ TopRight,
+ BottomLeft,
+ BottomRight,
+ Center
+ }
+}
diff --git a/Client/Assembly-CSharp/GoogleMobileAds/Api/AdRequest.cs b/Client/Assembly-CSharp/GoogleMobileAds/Api/AdRequest.cs
new file mode 100644
index 0000000..a303ea9
--- /dev/null
+++ b/Client/Assembly-CSharp/GoogleMobileAds/Api/AdRequest.cs
@@ -0,0 +1,113 @@
+using System;
+using System.Collections.Generic;
+using GoogleMobileAds.Api.Mediation;
+
+namespace GoogleMobileAds.Api
+{
+ public class AdRequest
+ {
+ public List<string> TestDevices { get; private set; }
+
+ public HashSet<string> Keywords { get; private set; }
+
+ public DateTime? Birthday { get; private set; }
+
+ public Gender? Gender { get; private set; }
+
+ public bool? TagForChildDirectedTreatment { get; private set; }
+
+ public Dictionary<string, string> Extras { get; private set; }
+
+ public List<MediationExtras> MediationExtras { get; private set; }
+
+ public const string Version = "3.17.0";
+
+ public const string TestDeviceSimulator = "SIMULATOR";
+
+ public class Builder
+ {
+ internal List<string> TestDevices { get; private set; }
+
+ internal HashSet<string> Keywords { get; private set; }
+
+ internal DateTime? Birthday { get; private set; }
+
+ internal Gender? Gender { get; private set; }
+
+ internal bool? ChildDirectedTreatmentTag { get; private set; }
+
+ internal Dictionary<string, string> Extras { get; private set; }
+
+ internal List<MediationExtras> MediationExtras { get; private set; }
+
+ public Builder()
+ {
+ this.TestDevices = new List<string>();
+ this.Keywords = new HashSet<string>();
+ this.Birthday = null;
+ this.Gender = null;
+ this.ChildDirectedTreatmentTag = null;
+ this.Extras = new Dictionary<string, string>();
+ this.MediationExtras = new List<MediationExtras>();
+ }
+
+ public AdRequest.Builder AddKeyword(string keyword)
+ {
+ this.Keywords.Add(keyword);
+ return this;
+ }
+
+ public AdRequest.Builder AddTestDevice(string deviceId)
+ {
+ this.TestDevices.Add(deviceId);
+ return this;
+ }
+
+ public AdRequest Build()
+ {
+ return new AdRequest(this);
+ }
+
+ public AdRequest.Builder SetBirthday(DateTime birthday)
+ {
+ this.Birthday = new DateTime?(birthday);
+ return this;
+ }
+
+ public AdRequest.Builder SetGender(Gender gender)
+ {
+ this.Gender = new Gender?(gender);
+ return this;
+ }
+
+ public AdRequest.Builder AddMediationExtras(MediationExtras extras)
+ {
+ this.MediationExtras.Add(extras);
+ return this;
+ }
+
+ public AdRequest.Builder TagForChildDirectedTreatment(bool tagForChildDirectedTreatment)
+ {
+ this.ChildDirectedTreatmentTag = new bool?(tagForChildDirectedTreatment);
+ return this;
+ }
+
+ public AdRequest.Builder AddExtra(string key, string value)
+ {
+ this.Extras.Add(key, value);
+ return this;
+ }
+ }
+
+ private AdRequest(AdRequest.Builder builder)
+ {
+ this.TestDevices = new List<string>(builder.TestDevices);
+ this.Keywords = new HashSet<string>(builder.Keywords);
+ this.Birthday = builder.Birthday;
+ this.Gender = builder.Gender;
+ this.TagForChildDirectedTreatment = builder.ChildDirectedTreatmentTag;
+ this.Extras = new Dictionary<string, string>(builder.Extras);
+ this.MediationExtras = builder.MediationExtras;
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/GoogleMobileAds/Api/AdSize.cs b/Client/Assembly-CSharp/GoogleMobileAds/Api/AdSize.cs
new file mode 100644
index 0000000..ec5f3f1
--- /dev/null
+++ b/Client/Assembly-CSharp/GoogleMobileAds/Api/AdSize.cs
@@ -0,0 +1,88 @@
+using System;
+
+namespace GoogleMobileAds.Api
+{
+ public class AdSize
+ {
+ public int Width
+ {
+ get
+ {
+ return this.width;
+ }
+ }
+
+ public int Height
+ {
+ get
+ {
+ return this.height;
+ }
+ }
+
+ public bool IsSmartBanner
+ {
+ get
+ {
+ return this.isSmartBanner;
+ }
+ }
+
+ private bool isSmartBanner;
+
+ private int width;
+
+ private int height;
+
+ public static readonly AdSize Banner = new AdSize(320, 50);
+
+ public static readonly AdSize MediumRectangle = new AdSize(300, 250);
+
+ public static readonly AdSize IABBanner = new AdSize(468, 60);
+
+ public static readonly AdSize Leaderboard = new AdSize(728, 90);
+
+ public static readonly AdSize SmartBanner = new AdSize(true);
+
+ public static readonly int FullWidth = -1;
+
+ public AdSize(int width, int height)
+ {
+ this.isSmartBanner = false;
+ this.width = width;
+ this.height = height;
+ }
+
+ private AdSize(bool isSmartBanner) : this(0, 0)
+ {
+ this.isSmartBanner = isSmartBanner;
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (obj == null || base.GetType() != obj.GetType())
+ {
+ return false;
+ }
+ AdSize adSize = (AdSize)obj;
+ return this.width == adSize.width && this.height == adSize.height && this.isSmartBanner == adSize.isSmartBanner;
+ }
+
+ public static bool operator ==(AdSize a, AdSize b)
+ {
+ return a.Equals(b);
+ }
+
+ public static bool operator !=(AdSize a, AdSize b)
+ {
+ return !a.Equals(b);
+ }
+
+ public override int GetHashCode()
+ {
+ int num = 71;
+ int num2 = 11;
+ return ((num * num2 ^ this.width.GetHashCode()) * num2 ^ this.height.GetHashCode()) * num2 ^ this.isSmartBanner.GetHashCode();
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/GoogleMobileAds/Api/AdapterState.cs b/Client/Assembly-CSharp/GoogleMobileAds/Api/AdapterState.cs
new file mode 100644
index 0000000..471e180
--- /dev/null
+++ b/Client/Assembly-CSharp/GoogleMobileAds/Api/AdapterState.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace GoogleMobileAds.Api
+{
+ public enum AdapterState
+ {
+ NotReady,
+ Ready
+ }
+}
diff --git a/Client/Assembly-CSharp/GoogleMobileAds/Api/AdapterStatus.cs b/Client/Assembly-CSharp/GoogleMobileAds/Api/AdapterStatus.cs
new file mode 100644
index 0000000..31451e3
--- /dev/null
+++ b/Client/Assembly-CSharp/GoogleMobileAds/Api/AdapterStatus.cs
@@ -0,0 +1,20 @@
+using System;
+
+namespace GoogleMobileAds.Api
+{
+ public class AdapterStatus
+ {
+ public AdapterState InitializationState { get; private set; }
+
+ public string Description { get; private set; }
+
+ public int Latency { get; private set; }
+
+ internal AdapterStatus(AdapterState state, string description, int latency)
+ {
+ this.InitializationState = state;
+ this.Description = description;
+ this.Latency = latency;
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/GoogleMobileAds/Api/BannerView.cs b/Client/Assembly-CSharp/GoogleMobileAds/Api/BannerView.cs
new file mode 100644
index 0000000..7ad2724
--- /dev/null
+++ b/Client/Assembly-CSharp/GoogleMobileAds/Api/BannerView.cs
@@ -0,0 +1,121 @@
+using System;
+using System.Reflection;
+using GoogleMobileAds.Common;
+
+namespace GoogleMobileAds.Api
+{
+ public class BannerView
+ {
+ public event EventHandler<EventArgs> OnAdLoaded;
+
+ public event EventHandler<AdFailedToLoadEventArgs> OnAdFailedToLoad;
+
+ public event EventHandler<EventArgs> OnAdOpening;
+
+ public event EventHandler<EventArgs> OnAdClosed;
+
+ public event EventHandler<EventArgs> OnAdLeavingApplication;
+
+ private IBannerClient client;
+
+ public BannerView(string adUnitId, AdSize adSize, AdPosition position)
+ {
+ MethodInfo method = Type.GetType("GoogleMobileAds.GoogleMobileAdsClientFactory,Assembly-CSharp").GetMethod("BuildBannerClient", BindingFlags.Static | BindingFlags.Public);
+ this.client = (IBannerClient)method.Invoke(null, null);
+ this.client.CreateBannerView(adUnitId, adSize, position);
+ this.ConfigureBannerEvents();
+ }
+
+ public BannerView(string adUnitId, AdSize adSize, int x, int y)
+ {
+ MethodInfo method = Type.GetType("GoogleMobileAds.GoogleMobileAdsClientFactory,Assembly-CSharp").GetMethod("BuildBannerClient", BindingFlags.Static | BindingFlags.Public);
+ this.client = (IBannerClient)method.Invoke(null, null);
+ this.client.CreateBannerView(adUnitId, adSize, x, y);
+ this.ConfigureBannerEvents();
+ }
+
+ public void LoadAd(AdRequest request)
+ {
+ this.client.LoadAd(request);
+ }
+
+ public void Hide()
+ {
+ this.client.HideBannerView();
+ }
+
+ public void Show()
+ {
+ this.client.ShowBannerView();
+ }
+
+ public void Destroy()
+ {
+ this.client.DestroyBannerView();
+ }
+
+ public float GetHeightInPixels()
+ {
+ return this.client.GetHeightInPixels();
+ }
+
+ public float GetWidthInPixels()
+ {
+ return this.client.GetWidthInPixels();
+ }
+
+ public void SetPosition(AdPosition adPosition)
+ {
+ this.client.SetPosition(adPosition);
+ }
+
+ public void SetPosition(int x, int y)
+ {
+ this.client.SetPosition(x, y);
+ }
+
+ private void ConfigureBannerEvents()
+ {
+ this.client.OnAdLoaded += delegate(object sender, EventArgs args)
+ {
+ if (this.OnAdLoaded != null)
+ {
+ this.OnAdLoaded(this, args);
+ }
+ };
+ this.client.OnAdFailedToLoad += delegate(object sender, AdFailedToLoadEventArgs args)
+ {
+ if (this.OnAdFailedToLoad != null)
+ {
+ this.OnAdFailedToLoad(this, args);
+ }
+ };
+ this.client.OnAdOpening += delegate(object sender, EventArgs args)
+ {
+ if (this.OnAdOpening != null)
+ {
+ this.OnAdOpening(this, args);
+ }
+ };
+ this.client.OnAdClosed += delegate(object sender, EventArgs args)
+ {
+ if (this.OnAdClosed != null)
+ {
+ this.OnAdClosed(this, args);
+ }
+ };
+ this.client.OnAdLeavingApplication += delegate(object sender, EventArgs args)
+ {
+ if (this.OnAdLeavingApplication != null)
+ {
+ this.OnAdLeavingApplication(this, args);
+ }
+ };
+ }
+
+ public string MediationAdapterClassName()
+ {
+ return this.client.MediationAdapterClassName();
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/GoogleMobileAds/Api/CustomNativeEventArgs.cs b/Client/Assembly-CSharp/GoogleMobileAds/Api/CustomNativeEventArgs.cs
new file mode 100644
index 0000000..692b54b
--- /dev/null
+++ b/Client/Assembly-CSharp/GoogleMobileAds/Api/CustomNativeEventArgs.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace GoogleMobileAds.Api
+{
+ public class CustomNativeEventArgs : EventArgs
+ {
+ public CustomNativeTemplateAd nativeAd { get; set; }
+ }
+}
diff --git a/Client/Assembly-CSharp/GoogleMobileAds/Api/CustomNativeTemplateAd.cs b/Client/Assembly-CSharp/GoogleMobileAds/Api/CustomNativeTemplateAd.cs
new file mode 100644
index 0000000..159341b
--- /dev/null
+++ b/Client/Assembly-CSharp/GoogleMobileAds/Api/CustomNativeTemplateAd.cs
@@ -0,0 +1,52 @@
+using System;
+using System.Collections.Generic;
+using GoogleMobileAds.Common;
+using UnityEngine;
+
+namespace GoogleMobileAds.Api
+{
+ public class CustomNativeTemplateAd
+ {
+ private ICustomNativeTemplateClient client;
+
+ internal CustomNativeTemplateAd(ICustomNativeTemplateClient client)
+ {
+ this.client = client;
+ }
+
+ public List<string> GetAvailableAssetNames()
+ {
+ return this.client.GetAvailableAssetNames();
+ }
+
+ public string GetCustomTemplateId()
+ {
+ return this.client.GetTemplateId();
+ }
+
+ public Texture2D GetTexture2D(string key)
+ {
+ byte[] imageByteArray = this.client.GetImageByteArray(key);
+ if (imageByteArray == null)
+ {
+ return null;
+ }
+ return Utils.GetTexture2DFromByteArray(imageByteArray);
+ }
+
+ public string GetText(string key)
+ {
+ return this.client.GetText(key);
+ }
+
+ public void PerformClick(string assetName)
+ {
+ this.client.PerformClick(assetName);
+ }
+
+ public void RecordImpression()
+ {
+ this.client.RecordImpression();
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/GoogleMobileAds/Api/Gender.cs b/Client/Assembly-CSharp/GoogleMobileAds/Api/Gender.cs
new file mode 100644
index 0000000..afdd035
--- /dev/null
+++ b/Client/Assembly-CSharp/GoogleMobileAds/Api/Gender.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace GoogleMobileAds.Api
+{
+ public enum Gender
+ {
+ Unknown,
+ Male,
+ Female
+ }
+}
diff --git a/Client/Assembly-CSharp/GoogleMobileAds/Api/InterstitialAd.cs b/Client/Assembly-CSharp/GoogleMobileAds/Api/InterstitialAd.cs
new file mode 100644
index 0000000..e9817bb
--- /dev/null
+++ b/Client/Assembly-CSharp/GoogleMobileAds/Api/InterstitialAd.cs
@@ -0,0 +1,88 @@
+using System;
+using System.Reflection;
+using GoogleMobileAds.Common;
+
+namespace GoogleMobileAds.Api
+{
+ public class InterstitialAd
+ {
+ public event EventHandler<EventArgs> OnAdLoaded;
+
+ public event EventHandler<AdFailedToLoadEventArgs> OnAdFailedToLoad;
+
+ public event EventHandler<EventArgs> OnAdOpening;
+
+ public event EventHandler<EventArgs> OnAdClosed;
+
+ public event EventHandler<EventArgs> OnAdLeavingApplication;
+
+ private IInterstitialClient client;
+
+ public InterstitialAd(string adUnitId)
+ {
+ MethodInfo method = Type.GetType("GoogleMobileAds.GoogleMobileAdsClientFactory,Assembly-CSharp").GetMethod("BuildInterstitialClient", BindingFlags.Static | BindingFlags.Public);
+ this.client = (IInterstitialClient)method.Invoke(null, null);
+ this.client.CreateInterstitialAd(adUnitId);
+ this.client.OnAdLoaded += delegate(object sender, EventArgs args)
+ {
+ if (this.OnAdLoaded != null)
+ {
+ this.OnAdLoaded(this, args);
+ }
+ };
+ this.client.OnAdFailedToLoad += delegate(object sender, AdFailedToLoadEventArgs args)
+ {
+ if (this.OnAdFailedToLoad != null)
+ {
+ this.OnAdFailedToLoad(this, args);
+ }
+ };
+ this.client.OnAdOpening += delegate(object sender, EventArgs args)
+ {
+ if (this.OnAdOpening != null)
+ {
+ this.OnAdOpening(this, args);
+ }
+ };
+ this.client.OnAdClosed += delegate(object sender, EventArgs args)
+ {
+ if (this.OnAdClosed != null)
+ {
+ this.OnAdClosed(this, args);
+ }
+ };
+ this.client.OnAdLeavingApplication += delegate(object sender, EventArgs args)
+ {
+ if (this.OnAdLeavingApplication != null)
+ {
+ this.OnAdLeavingApplication(this, args);
+ }
+ };
+ }
+
+ public void LoadAd(AdRequest request)
+ {
+ this.client.LoadAd(request);
+ }
+
+ public bool IsLoaded()
+ {
+ return this.client.IsLoaded();
+ }
+
+ public void Show()
+ {
+ this.client.ShowInterstitial();
+ }
+
+ public void Destroy()
+ {
+ this.client.DestroyInterstitial();
+ }
+
+ public string MediationAdapterClassName()
+ {
+ return this.client.MediationAdapterClassName();
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/GoogleMobileAds/Api/Mediation/MediationExtras.cs b/Client/Assembly-CSharp/GoogleMobileAds/Api/Mediation/MediationExtras.cs
new file mode 100644
index 0000000..1604ec7
--- /dev/null
+++ b/Client/Assembly-CSharp/GoogleMobileAds/Api/Mediation/MediationExtras.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+
+namespace GoogleMobileAds.Api.Mediation
+{
+ public abstract class MediationExtras
+ {
+ public Dictionary<string, string> Extras { get; protected set; }
+
+ public abstract string AndroidMediationExtraBuilderClassName { get; }
+
+ public abstract string IOSMediationExtraBuilderClassName { get; }
+
+ public MediationExtras()
+ {
+ this.Extras = new Dictionary<string, string>();
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/GoogleMobileAds/Api/MobileAds.cs b/Client/Assembly-CSharp/GoogleMobileAds/Api/MobileAds.cs
new file mode 100644
index 0000000..38199b3
--- /dev/null
+++ b/Client/Assembly-CSharp/GoogleMobileAds/Api/MobileAds.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Reflection;
+using GoogleMobileAds.Common;
+
+namespace GoogleMobileAds.Api
+{
+ public class MobileAds
+ {
+ private static readonly IMobileAdsClient client = MobileAds.GetMobileAdsClient();
+
+ public static void Initialize(string appId)
+ {
+ MobileAds.client.Initialize(appId);
+ MobileAdsEventExecutor.Initialize();
+ }
+
+ public static void SetApplicationMuted(bool muted)
+ {
+ MobileAds.client.SetApplicationMuted(muted);
+ }
+
+ public static void SetApplicationVolume(float volume)
+ {
+ MobileAds.client.SetApplicationVolume(volume);
+ }
+
+ public static void SetiOSAppPauseOnBackground(bool pause)
+ {
+ MobileAds.client.SetiOSAppPauseOnBackground(pause);
+ }
+
+ private static IMobileAdsClient GetMobileAdsClient()
+ {
+ return (IMobileAdsClient)Type.GetType("GoogleMobileAds.GoogleMobileAdsClientFactory,Assembly-CSharp").GetMethod("MobileAdsInstance", BindingFlags.Static | BindingFlags.Public).Invoke(null, null);
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/GoogleMobileAds/Api/NativeAdType.cs b/Client/Assembly-CSharp/GoogleMobileAds/Api/NativeAdType.cs
new file mode 100644
index 0000000..98c1e39
--- /dev/null
+++ b/Client/Assembly-CSharp/GoogleMobileAds/Api/NativeAdType.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace GoogleMobileAds.Api
+{
+ public enum NativeAdType
+ {
+ CustomTemplate
+ }
+}
diff --git a/Client/Assembly-CSharp/GoogleMobileAds/Api/Reward.cs b/Client/Assembly-CSharp/GoogleMobileAds/Api/Reward.cs
new file mode 100644
index 0000000..1e0beda
--- /dev/null
+++ b/Client/Assembly-CSharp/GoogleMobileAds/Api/Reward.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace GoogleMobileAds.Api
+{
+ public class Reward : EventArgs
+ {
+ public string Type { get; set; }
+
+ public double Amount { get; set; }
+ }
+}
diff --git a/Client/Assembly-CSharp/GoogleMobileAds/Api/RewardBasedVideoAd.cs b/Client/Assembly-CSharp/GoogleMobileAds/Api/RewardBasedVideoAd.cs
new file mode 100644
index 0000000..90f069a
--- /dev/null
+++ b/Client/Assembly-CSharp/GoogleMobileAds/Api/RewardBasedVideoAd.cs
@@ -0,0 +1,125 @@
+using System;
+using System.Reflection;
+using GoogleMobileAds.Common;
+
+namespace GoogleMobileAds.Api
+{
+ public class RewardBasedVideoAd
+ {
+ public static RewardBasedVideoAd Instance
+ {
+ get
+ {
+ return RewardBasedVideoAd.instance;
+ }
+ }
+
+ public event EventHandler<EventArgs> OnAdLoaded;
+
+ public event EventHandler<AdFailedToLoadEventArgs> OnAdFailedToLoad;
+
+ public event EventHandler<EventArgs> OnAdOpening;
+
+ public event EventHandler<EventArgs> OnAdStarted;
+
+ public event EventHandler<EventArgs> OnAdClosed;
+
+ public event EventHandler<Reward> OnAdRewarded;
+
+ public event EventHandler<EventArgs> OnAdLeavingApplication;
+
+ public event EventHandler<EventArgs> OnAdCompleted;
+
+ private IRewardBasedVideoAdClient client;
+
+ private static readonly RewardBasedVideoAd instance = new RewardBasedVideoAd();
+
+ private RewardBasedVideoAd()
+ {
+ MethodInfo method = Type.GetType("GoogleMobileAds.GoogleMobileAdsClientFactory,Assembly-CSharp").GetMethod("BuildRewardBasedVideoAdClient", BindingFlags.Static | BindingFlags.Public);
+ this.client = (IRewardBasedVideoAdClient)method.Invoke(null, null);
+ this.client.CreateRewardBasedVideoAd();
+ this.client.OnAdLoaded += delegate(object sender, EventArgs args)
+ {
+ if (this.OnAdLoaded != null)
+ {
+ this.OnAdLoaded(this, args);
+ }
+ };
+ this.client.OnAdFailedToLoad += delegate(object sender, AdFailedToLoadEventArgs args)
+ {
+ if (this.OnAdFailedToLoad != null)
+ {
+ this.OnAdFailedToLoad(this, args);
+ }
+ };
+ this.client.OnAdOpening += delegate(object sender, EventArgs args)
+ {
+ if (this.OnAdOpening != null)
+ {
+ this.OnAdOpening(this, args);
+ }
+ };
+ this.client.OnAdStarted += delegate(object sender, EventArgs args)
+ {
+ if (this.OnAdStarted != null)
+ {
+ this.OnAdStarted(this, args);
+ }
+ };
+ this.client.OnAdClosed += delegate(object sender, EventArgs args)
+ {
+ if (this.OnAdClosed != null)
+ {
+ this.OnAdClosed(this, args);
+ }
+ };
+ this.client.OnAdLeavingApplication += delegate(object sender, EventArgs args)
+ {
+ if (this.OnAdLeavingApplication != null)
+ {
+ this.OnAdLeavingApplication(this, args);
+ }
+ };
+ this.client.OnAdRewarded += delegate(object sender, Reward args)
+ {
+ if (this.OnAdRewarded != null)
+ {
+ this.OnAdRewarded(this, args);
+ }
+ };
+ this.client.OnAdCompleted += delegate(object sender, EventArgs args)
+ {
+ if (this.OnAdCompleted != null)
+ {
+ this.OnAdCompleted(this, args);
+ }
+ };
+ }
+
+ public void LoadAd(AdRequest request, string adUnitId)
+ {
+ this.client.LoadAd(request, adUnitId);
+ }
+
+ public bool IsLoaded()
+ {
+ return this.client.IsLoaded();
+ }
+
+ public void Show()
+ {
+ this.client.ShowRewardBasedVideoAd();
+ }
+
+ public void SetUserId(string userId)
+ {
+ this.client.SetUserId(userId);
+ }
+
+ public string MediationAdapterClassName()
+ {
+ return this.client.MediationAdapterClassName();
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/GoogleMobileAds/Api/RewardedAd.cs b/Client/Assembly-CSharp/GoogleMobileAds/Api/RewardedAd.cs
new file mode 100644
index 0000000..48a43ff
--- /dev/null
+++ b/Client/Assembly-CSharp/GoogleMobileAds/Api/RewardedAd.cs
@@ -0,0 +1,97 @@
+using System;
+using System.Reflection;
+using GoogleMobileAds.Common;
+
+namespace GoogleMobileAds.Api
+{
+ public class RewardedAd
+ {
+ public event EventHandler<EventArgs> OnAdLoaded;
+
+ public event EventHandler<AdErrorEventArgs> OnAdFailedToLoad;
+
+ public event EventHandler<AdErrorEventArgs> OnAdFailedToShow;
+
+ public event EventHandler<EventArgs> OnAdOpening;
+
+ public event EventHandler<EventArgs> OnAdClosed;
+
+ public event EventHandler<Reward> OnUserEarnedReward;
+
+ private IRewardedAdClient client;
+
+ public RewardedAd(string adUnitId)
+ {
+ MethodInfo method = Type.GetType("GoogleMobileAds.GoogleMobileAdsClientFactory,Assembly-CSharp").GetMethod("BuildRewardedAdClient", BindingFlags.Static | BindingFlags.Public);
+ this.client = (IRewardedAdClient)method.Invoke(null, null);
+ this.client.CreateRewardedAd(adUnitId);
+ this.client.OnAdLoaded += delegate(object sender, EventArgs args)
+ {
+ if (this.OnAdLoaded != null)
+ {
+ this.OnAdLoaded(this, args);
+ }
+ };
+ this.client.OnAdFailedToLoad += delegate(object sender, AdErrorEventArgs args)
+ {
+ if (this.OnAdFailedToLoad != null)
+ {
+ this.OnAdFailedToLoad(this, args);
+ }
+ };
+ this.client.OnAdFailedToShow += delegate(object sender, AdErrorEventArgs args)
+ {
+ if (this.OnAdFailedToShow != null)
+ {
+ this.OnAdFailedToShow(this, args);
+ }
+ };
+ this.client.OnAdOpening += delegate(object sender, EventArgs args)
+ {
+ if (this.OnAdOpening != null)
+ {
+ this.OnAdOpening(this, args);
+ }
+ };
+ this.client.OnAdClosed += delegate(object sender, EventArgs args)
+ {
+ if (this.OnAdClosed != null)
+ {
+ this.OnAdClosed(this, args);
+ }
+ };
+ this.client.OnUserEarnedReward += delegate(object sender, Reward args)
+ {
+ if (this.OnUserEarnedReward != null)
+ {
+ this.OnUserEarnedReward(this, args);
+ }
+ };
+ }
+
+ public void LoadAd(AdRequest request)
+ {
+ this.client.LoadAd(request);
+ }
+
+ public bool IsLoaded()
+ {
+ return this.client.IsLoaded();
+ }
+
+ public void Show()
+ {
+ this.client.Show();
+ }
+
+ public void SetServerSideVerificationOptions(ServerSideVerificationOptions serverSideVerificationOptions)
+ {
+ this.client.SetServerSideVerificationOptions(serverSideVerificationOptions);
+ }
+
+ public string MediationAdapterClassName()
+ {
+ return this.client.MediationAdapterClassName();
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/GoogleMobileAds/Api/ServerSideVerificationOptions.cs b/Client/Assembly-CSharp/GoogleMobileAds/Api/ServerSideVerificationOptions.cs
new file mode 100644
index 0000000..6f0e920
--- /dev/null
+++ b/Client/Assembly-CSharp/GoogleMobileAds/Api/ServerSideVerificationOptions.cs
@@ -0,0 +1,41 @@
+using System;
+
+namespace GoogleMobileAds.Api
+{
+ public class ServerSideVerificationOptions
+ {
+ public string UserId { get; private set; }
+
+ public string CustomData { get; private set; }
+
+ public class Builder
+ {
+ internal string UserId { get; private set; }
+
+ internal string CustomData { get; private set; }
+
+ public ServerSideVerificationOptions.Builder SetUserId(string userId)
+ {
+ this.UserId = userId;
+ return this;
+ }
+
+ public ServerSideVerificationOptions.Builder SetCustomData(string customData)
+ {
+ this.CustomData = customData;
+ return this;
+ }
+
+ public ServerSideVerificationOptions Build()
+ {
+ return new ServerSideVerificationOptions(this);
+ }
+ }
+
+ private ServerSideVerificationOptions(ServerSideVerificationOptions.Builder builder)
+ {
+ this.UserId = builder.UserId;
+ this.CustomData = builder.CustomData;
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/GoogleMobileAds/Common/DummyClient.cs b/Client/Assembly-CSharp/GoogleMobileAds/Common/DummyClient.cs
new file mode 100644
index 0000000..91587cc
--- /dev/null
+++ b/Client/Assembly-CSharp/GoogleMobileAds/Common/DummyClient.cs
@@ -0,0 +1,185 @@
+using System;
+using System.Reflection;
+using GoogleMobileAds.Api;
+using UnityEngine;
+
+namespace GoogleMobileAds.Common
+{
+ public class DummyClient : IBannerClient, IInterstitialClient, IRewardBasedVideoAdClient, IAdLoaderClient, IMobileAdsClient
+ {
+ public string UserId
+ {
+ get
+ {
+ Debug.Log("Dummy " + MethodBase.GetCurrentMethod().Name);
+ return "UserId";
+ }
+ set
+ {
+ Debug.Log("Dummy " + MethodBase.GetCurrentMethod().Name);
+ }
+ }
+
+ public event EventHandler<EventArgs> OnAdLoaded;
+
+ public event EventHandler<AdFailedToLoadEventArgs> OnAdFailedToLoad;
+
+ public event EventHandler<EventArgs> OnAdOpening;
+
+ public event EventHandler<EventArgs> OnAdStarted;
+
+ public event EventHandler<EventArgs> OnAdClosed;
+
+ public event EventHandler<Reward> OnAdRewarded;
+
+ public event EventHandler<EventArgs> OnAdLeavingApplication;
+
+ public event EventHandler<EventArgs> OnAdCompleted;
+
+ public event EventHandler<CustomNativeEventArgs> OnCustomNativeTemplateAdLoaded;
+
+ public DummyClient()
+ {
+ Debug.Log("Dummy " + MethodBase.GetCurrentMethod().Name);
+ }
+
+ public void Initialize(string appId)
+ {
+ Debug.Log("Dummy " + MethodBase.GetCurrentMethod().Name);
+ }
+
+ public void SetApplicationMuted(bool muted)
+ {
+ Debug.Log("Dummy " + MethodBase.GetCurrentMethod().Name);
+ }
+
+ public void SetApplicationVolume(float volume)
+ {
+ Debug.Log("Dummy " + MethodBase.GetCurrentMethod().Name);
+ }
+
+ public void SetiOSAppPauseOnBackground(bool pause)
+ {
+ Debug.Log("Dummy " + MethodBase.GetCurrentMethod().Name);
+ }
+
+ public void CreateBannerView(string adUnitId, AdSize adSize, AdPosition position)
+ {
+ Debug.Log("Dummy " + MethodBase.GetCurrentMethod().Name);
+ }
+
+ public void CreateBannerView(string adUnitId, AdSize adSize, int positionX, int positionY)
+ {
+ Debug.Log("Dummy " + MethodBase.GetCurrentMethod().Name);
+ }
+
+ public void LoadAd(AdRequest request)
+ {
+ Debug.Log("Dummy " + MethodBase.GetCurrentMethod().Name);
+ }
+
+ public void ShowBannerView()
+ {
+ Debug.Log("Dummy " + MethodBase.GetCurrentMethod().Name);
+ }
+
+ public void HideBannerView()
+ {
+ Debug.Log("Dummy " + MethodBase.GetCurrentMethod().Name);
+ }
+
+ public void DestroyBannerView()
+ {
+ Debug.Log("Dummy " + MethodBase.GetCurrentMethod().Name);
+ }
+
+ public float GetHeightInPixels()
+ {
+ Debug.Log("Dummy " + MethodBase.GetCurrentMethod().Name);
+ return 0f;
+ }
+
+ public float GetWidthInPixels()
+ {
+ Debug.Log("Dummy " + MethodBase.GetCurrentMethod().Name);
+ return 0f;
+ }
+
+ public void SetPosition(AdPosition adPosition)
+ {
+ Debug.Log("Dummy " + MethodBase.GetCurrentMethod().Name);
+ }
+
+ public void SetPosition(int x, int y)
+ {
+ Debug.Log("Dummy " + MethodBase.GetCurrentMethod().Name);
+ }
+
+ public void CreateInterstitialAd(string adUnitId)
+ {
+ Debug.Log("Dummy " + MethodBase.GetCurrentMethod().Name);
+ }
+
+ public bool IsLoaded()
+ {
+ Debug.Log("Dummy " + MethodBase.GetCurrentMethod().Name);
+ return true;
+ }
+
+ public void ShowInterstitial()
+ {
+ Debug.Log("Dummy " + MethodBase.GetCurrentMethod().Name);
+ }
+
+ public void DestroyInterstitial()
+ {
+ Debug.Log("Dummy " + MethodBase.GetCurrentMethod().Name);
+ }
+
+ public void CreateRewardBasedVideoAd()
+ {
+ Debug.Log("Dummy " + MethodBase.GetCurrentMethod().Name);
+ }
+
+ public void SetUserId(string userId)
+ {
+ Debug.Log("Dummy " + MethodBase.GetCurrentMethod().Name);
+ }
+
+ public void LoadAd(AdRequest request, string adUnitId)
+ {
+ Debug.Log("Dummy " + MethodBase.GetCurrentMethod().Name);
+ }
+
+ public void DestroyRewardBasedVideoAd()
+ {
+ Debug.Log("Dummy " + MethodBase.GetCurrentMethod().Name);
+ }
+
+ public void ShowRewardBasedVideoAd()
+ {
+ Debug.Log("Dummy " + MethodBase.GetCurrentMethod().Name);
+ }
+
+ public void CreateAdLoader(AdLoader.Builder builder)
+ {
+ Debug.Log("Dummy " + MethodBase.GetCurrentMethod().Name);
+ }
+
+ public void Load(AdRequest request)
+ {
+ Debug.Log("Dummy " + MethodBase.GetCurrentMethod().Name);
+ }
+
+ public void SetAdSize(AdSize adSize)
+ {
+ Debug.Log("Dummy " + MethodBase.GetCurrentMethod().Name);
+ }
+
+ public string MediationAdapterClassName()
+ {
+ Debug.Log("Dummy " + MethodBase.GetCurrentMethod().Name);
+ return null;
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/GoogleMobileAds/Common/IAdLoaderClient.cs b/Client/Assembly-CSharp/GoogleMobileAds/Common/IAdLoaderClient.cs
new file mode 100644
index 0000000..4f9f332
--- /dev/null
+++ b/Client/Assembly-CSharp/GoogleMobileAds/Common/IAdLoaderClient.cs
@@ -0,0 +1,14 @@
+using System;
+using GoogleMobileAds.Api;
+
+namespace GoogleMobileAds.Common
+{
+ public interface IAdLoaderClient
+ {
+ event EventHandler<AdFailedToLoadEventArgs> OnAdFailedToLoad;
+
+ event EventHandler<CustomNativeEventArgs> OnCustomNativeTemplateAdLoaded;
+
+ void LoadAd(AdRequest request);
+ }
+}
diff --git a/Client/Assembly-CSharp/GoogleMobileAds/Common/IBannerClient.cs b/Client/Assembly-CSharp/GoogleMobileAds/Common/IBannerClient.cs
new file mode 100644
index 0000000..96f2d37
--- /dev/null
+++ b/Client/Assembly-CSharp/GoogleMobileAds/Common/IBannerClient.cs
@@ -0,0 +1,40 @@
+using System;
+using GoogleMobileAds.Api;
+
+namespace GoogleMobileAds.Common
+{
+ public interface IBannerClient
+ {
+ event EventHandler<EventArgs> OnAdLoaded;
+
+ event EventHandler<AdFailedToLoadEventArgs> OnAdFailedToLoad;
+
+ event EventHandler<EventArgs> OnAdOpening;
+
+ event EventHandler<EventArgs> OnAdClosed;
+
+ event EventHandler<EventArgs> OnAdLeavingApplication;
+
+ void CreateBannerView(string adUnitId, AdSize adSize, AdPosition position);
+
+ void CreateBannerView(string adUnitId, AdSize adSize, int x, int y);
+
+ void LoadAd(AdRequest request);
+
+ void ShowBannerView();
+
+ void HideBannerView();
+
+ void DestroyBannerView();
+
+ float GetHeightInPixels();
+
+ float GetWidthInPixels();
+
+ void SetPosition(AdPosition adPosition);
+
+ void SetPosition(int x, int y);
+
+ string MediationAdapterClassName();
+ }
+}
diff --git a/Client/Assembly-CSharp/GoogleMobileAds/Common/ICustomNativeTemplateClient.cs b/Client/Assembly-CSharp/GoogleMobileAds/Common/ICustomNativeTemplateClient.cs
new file mode 100644
index 0000000..8c5ae57
--- /dev/null
+++ b/Client/Assembly-CSharp/GoogleMobileAds/Common/ICustomNativeTemplateClient.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+
+namespace GoogleMobileAds.Common
+{
+ public interface ICustomNativeTemplateClient
+ {
+ string GetTemplateId();
+
+ byte[] GetImageByteArray(string key);
+
+ List<string> GetAvailableAssetNames();
+
+ string GetText(string key);
+
+ void PerformClick(string assetName);
+
+ void RecordImpression();
+ }
+}
diff --git a/Client/Assembly-CSharp/GoogleMobileAds/Common/IInterstitialClient.cs b/Client/Assembly-CSharp/GoogleMobileAds/Common/IInterstitialClient.cs
new file mode 100644
index 0000000..cd4e35a
--- /dev/null
+++ b/Client/Assembly-CSharp/GoogleMobileAds/Common/IInterstitialClient.cs
@@ -0,0 +1,30 @@
+using System;
+using GoogleMobileAds.Api;
+
+namespace GoogleMobileAds.Common
+{
+ public interface IInterstitialClient
+ {
+ event EventHandler<EventArgs> OnAdLoaded;
+
+ event EventHandler<AdFailedToLoadEventArgs> OnAdFailedToLoad;
+
+ event EventHandler<EventArgs> OnAdOpening;
+
+ event EventHandler<EventArgs> OnAdClosed;
+
+ event EventHandler<EventArgs> OnAdLeavingApplication;
+
+ void CreateInterstitialAd(string adUnitId);
+
+ void LoadAd(AdRequest request);
+
+ bool IsLoaded();
+
+ void ShowInterstitial();
+
+ void DestroyInterstitial();
+
+ string MediationAdapterClassName();
+ }
+}
diff --git a/Client/Assembly-CSharp/GoogleMobileAds/Common/IMobileAdsClient.cs b/Client/Assembly-CSharp/GoogleMobileAds/Common/IMobileAdsClient.cs
new file mode 100644
index 0000000..a7735f2
--- /dev/null
+++ b/Client/Assembly-CSharp/GoogleMobileAds/Common/IMobileAdsClient.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace GoogleMobileAds.Common
+{
+ public interface IMobileAdsClient
+ {
+ void Initialize(string appId);
+
+ void SetApplicationVolume(float volume);
+
+ void SetApplicationMuted(bool muted);
+
+ void SetiOSAppPauseOnBackground(bool pause);
+ }
+}
diff --git a/Client/Assembly-CSharp/GoogleMobileAds/Common/IRewardBasedVideoAdClient.cs b/Client/Assembly-CSharp/GoogleMobileAds/Common/IRewardBasedVideoAdClient.cs
new file mode 100644
index 0000000..2e4589d
--- /dev/null
+++ b/Client/Assembly-CSharp/GoogleMobileAds/Common/IRewardBasedVideoAdClient.cs
@@ -0,0 +1,36 @@
+using System;
+using GoogleMobileAds.Api;
+
+namespace GoogleMobileAds.Common
+{
+ public interface IRewardBasedVideoAdClient
+ {
+ event EventHandler<EventArgs> OnAdLoaded;
+
+ event EventHandler<AdFailedToLoadEventArgs> OnAdFailedToLoad;
+
+ event EventHandler<EventArgs> OnAdOpening;
+
+ event EventHandler<EventArgs> OnAdStarted;
+
+ event EventHandler<Reward> OnAdRewarded;
+
+ event EventHandler<EventArgs> OnAdClosed;
+
+ event EventHandler<EventArgs> OnAdLeavingApplication;
+
+ event EventHandler<EventArgs> OnAdCompleted;
+
+ void CreateRewardBasedVideoAd();
+
+ void LoadAd(AdRequest request, string adUnitId);
+
+ bool IsLoaded();
+
+ string MediationAdapterClassName();
+
+ void ShowRewardBasedVideoAd();
+
+ void SetUserId(string userId);
+ }
+}
diff --git a/Client/Assembly-CSharp/GoogleMobileAds/Common/IRewardedAdClient.cs b/Client/Assembly-CSharp/GoogleMobileAds/Common/IRewardedAdClient.cs
new file mode 100644
index 0000000..10a8a6c
--- /dev/null
+++ b/Client/Assembly-CSharp/GoogleMobileAds/Common/IRewardedAdClient.cs
@@ -0,0 +1,32 @@
+using System;
+using GoogleMobileAds.Api;
+
+namespace GoogleMobileAds.Common
+{
+ public interface IRewardedAdClient
+ {
+ event EventHandler<EventArgs> OnAdLoaded;
+
+ event EventHandler<AdErrorEventArgs> OnAdFailedToLoad;
+
+ event EventHandler<AdErrorEventArgs> OnAdFailedToShow;
+
+ event EventHandler<EventArgs> OnAdOpening;
+
+ event EventHandler<Reward> OnUserEarnedReward;
+
+ event EventHandler<EventArgs> OnAdClosed;
+
+ void CreateRewardedAd(string adUnitId);
+
+ void LoadAd(AdRequest request);
+
+ bool IsLoaded();
+
+ string MediationAdapterClassName();
+
+ void Show();
+
+ void SetServerSideVerificationOptions(ServerSideVerificationOptions serverSideVerificationOptions);
+ }
+}
diff --git a/Client/Assembly-CSharp/GoogleMobileAds/Common/MobileAdsEventExecutor.cs b/Client/Assembly-CSharp/GoogleMobileAds/Common/MobileAdsEventExecutor.cs
new file mode 100644
index 0000000..8afa69c
--- /dev/null
+++ b/Client/Assembly-CSharp/GoogleMobileAds/Common/MobileAdsEventExecutor.cs
@@ -0,0 +1,72 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace GoogleMobileAds.Common
+{
+ public class MobileAdsEventExecutor : MonoBehaviour
+ {
+ public static MobileAdsEventExecutor instance = null;
+
+ private static List<Action> adEventsQueue = new List<Action>();
+
+ private static volatile bool adEventsQueueEmpty = true;
+
+ public static void Initialize()
+ {
+ if (MobileAdsEventExecutor.IsActive())
+ {
+ return;
+ }
+ GameObject gameObject = new GameObject("MobileAdsMainThreadExecuter");
+ gameObject.hideFlags = HideFlags.HideAndDontSave;
+ UnityEngine.Object.DontDestroyOnLoad(gameObject);
+ MobileAdsEventExecutor.instance = gameObject.AddComponent<MobileAdsEventExecutor>();
+ }
+
+ public static bool IsActive()
+ {
+ return MobileAdsEventExecutor.instance != null;
+ }
+
+ public void Awake()
+ {
+ UnityEngine.Object.DontDestroyOnLoad(base.gameObject);
+ }
+
+ public static void ExecuteInUpdate(Action action)
+ {
+ List<Action> obj = MobileAdsEventExecutor.adEventsQueue;
+ lock (obj)
+ {
+ MobileAdsEventExecutor.adEventsQueue.Add(action);
+ MobileAdsEventExecutor.adEventsQueueEmpty = false;
+ }
+ }
+
+ public void Update()
+ {
+ if (MobileAdsEventExecutor.adEventsQueueEmpty)
+ {
+ return;
+ }
+ List<Action> list = new List<Action>();
+ List<Action> obj = MobileAdsEventExecutor.adEventsQueue;
+ lock (obj)
+ {
+ list.AddRange(MobileAdsEventExecutor.adEventsQueue);
+ MobileAdsEventExecutor.adEventsQueue.Clear();
+ MobileAdsEventExecutor.adEventsQueueEmpty = true;
+ }
+ foreach (Action action in list)
+ {
+ action();
+ }
+ }
+
+ public void OnDisable()
+ {
+ MobileAdsEventExecutor.instance = null;
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/GoogleMobileAds/Common/RewardedAdDummyClient.cs b/Client/Assembly-CSharp/GoogleMobileAds/Common/RewardedAdDummyClient.cs
new file mode 100644
index 0000000..1271c6d
--- /dev/null
+++ b/Client/Assembly-CSharp/GoogleMobileAds/Common/RewardedAdDummyClient.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Reflection;
+using GoogleMobileAds.Api;
+using UnityEngine;
+
+namespace GoogleMobileAds.Common
+{
+ public class RewardedAdDummyClient : IRewardedAdClient
+ {
+ public event EventHandler<EventArgs> OnAdLoaded;
+
+ public event EventHandler<AdErrorEventArgs> OnAdFailedToLoad;
+
+ public event EventHandler<AdErrorEventArgs> OnAdFailedToShow;
+
+ public event EventHandler<EventArgs> OnAdOpening;
+
+ public event EventHandler<EventArgs> OnAdClosed;
+
+ public event EventHandler<Reward> OnUserEarnedReward;
+
+ public RewardedAdDummyClient()
+ {
+ Debug.Log("Dummy " + MethodBase.GetCurrentMethod().Name);
+ }
+
+ public void CreateRewardedAd(string adUnitId)
+ {
+ Debug.Log("Dummy " + MethodBase.GetCurrentMethod().Name);
+ }
+
+ public void LoadAd(AdRequest request)
+ {
+ Debug.Log("Dummy " + MethodBase.GetCurrentMethod().Name);
+ }
+
+ public bool IsLoaded()
+ {
+ Debug.Log("Dummy " + MethodBase.GetCurrentMethod().Name);
+ return true;
+ }
+
+ public void Show()
+ {
+ Debug.Log("Dummy " + MethodBase.GetCurrentMethod().Name);
+ }
+
+ public string MediationAdapterClassName()
+ {
+ Debug.Log("Dummy " + MethodBase.GetCurrentMethod().Name);
+ return null;
+ }
+
+ public void SetServerSideVerificationOptions(ServerSideVerificationOptions serverSideVerificationOptions)
+ {
+ Debug.Log("Dummy " + MethodBase.GetCurrentMethod().Name);
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/GoogleMobileAds/Common/Utils.cs b/Client/Assembly-CSharp/GoogleMobileAds/Common/Utils.cs
new file mode 100644
index 0000000..cd20f95
--- /dev/null
+++ b/Client/Assembly-CSharp/GoogleMobileAds/Common/Utils.cs
@@ -0,0 +1,27 @@
+using System;
+using UnityEngine;
+
+namespace GoogleMobileAds.Common
+{
+ internal class Utils
+ {
+ public static void CheckInitialization()
+ {
+ if (!MobileAdsEventExecutor.IsActive())
+ {
+ Debug.Log("You intitialized an ad object but have not yet called MobileAds.Initialize(). We highly recommend you call MobileAds.Initialize() before interacting with the Google Mobile Ads SDK.");
+ }
+ MobileAdsEventExecutor.Initialize();
+ }
+
+ public static Texture2D GetTexture2DFromByteArray(byte[] img)
+ {
+ Texture2D texture2D = new Texture2D(1, 1);
+ if (!texture2D.LoadImage(img))
+ {
+ throw new InvalidOperationException("Could not load custom native template\n image asset as texture");
+ }
+ return texture2D;
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/GoogleMobileAds/GoogleMobileAdsClientFactory.cs b/Client/Assembly-CSharp/GoogleMobileAds/GoogleMobileAdsClientFactory.cs
new file mode 100644
index 0000000..1e5fcaa
--- /dev/null
+++ b/Client/Assembly-CSharp/GoogleMobileAds/GoogleMobileAdsClientFactory.cs
@@ -0,0 +1,39 @@
+using System;
+using GoogleMobileAds.Api;
+using GoogleMobileAds.Common;
+
+namespace GoogleMobileAds
+{
+ public class GoogleMobileAdsClientFactory
+ {
+ public static IBannerClient BuildBannerClient()
+ {
+ return new DummyClient();
+ }
+
+ public static IInterstitialClient BuildInterstitialClient()
+ {
+ return new DummyClient();
+ }
+
+ public static IRewardBasedVideoAdClient BuildRewardBasedVideoAdClient()
+ {
+ return new DummyClient();
+ }
+
+ public static IRewardedAdClient BuildRewardedAdClient()
+ {
+ return new RewardedAdDummyClient();
+ }
+
+ public static IAdLoaderClient BuildAdLoaderClient(AdLoader adLoader)
+ {
+ return new DummyClient();
+ }
+
+ public static IMobileAdsClient MobileAdsInstance()
+ {
+ return new DummyClient();
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/HashRandom.cs b/Client/Assembly-CSharp/HashRandom.cs
new file mode 100644
index 0000000..7d226b1
--- /dev/null
+++ b/Client/Assembly-CSharp/HashRandom.cs
@@ -0,0 +1,36 @@
+using System;
+
+public static class HashRandom
+{
+ private static XXHash src = new XXHash((int)DateTime.UtcNow.Ticks);
+
+ private static int cnt = 0;
+
+ public static uint Next()
+ {
+ return HashRandom.src.GetHash(HashRandom.cnt++);
+ }
+
+ public static int FastNext(int maxInt)
+ {
+ return (int)((ulong)HashRandom.Next() % (ulong)((long)maxInt));
+ }
+
+ public static int Next(int maxInt)
+ {
+ uint num = (uint)(-1 / maxInt);
+ uint num2 = num * (uint)maxInt;
+ uint num3;
+ do
+ {
+ num3 = HashRandom.Next();
+ }
+ while (num3 > num2);
+ return (int)(num3 / num);
+ }
+
+ public static int Next(int minInt, int maxInt)
+ {
+ return HashRandom.Next(maxInt - minInt) + minInt;
+ }
+}
diff --git a/Client/Assembly-CSharp/HatBehaviour.cs b/Client/Assembly-CSharp/HatBehaviour.cs
new file mode 100644
index 0000000..95d4b25
--- /dev/null
+++ b/Client/Assembly-CSharp/HatBehaviour.cs
@@ -0,0 +1,34 @@
+using System;
+using UnityEngine;
+
+[CreateAssetMenu]
+public class HatBehaviour : ScriptableObject, IBuyable
+{
+ public string ProdId
+ {
+ get
+ {
+ return this.ProductId;
+ }
+ }
+
+ public Sprite MainImage;
+
+ public Sprite FloorImage;
+
+ public bool InFront;
+
+ public bool Free;
+
+ public int LimitedMonth;
+
+ public int LimitedYear;
+
+ public SkinData RelatedSkin;
+
+ public string StoreName;
+
+ public string ProductId;
+
+ public int Order;
+}
diff --git a/Client/Assembly-CSharp/HatManager.cs b/Client/Assembly-CSharp/HatManager.cs
new file mode 100644
index 0000000..4c57c44
--- /dev/null
+++ b/Client/Assembly-CSharp/HatManager.cs
@@ -0,0 +1,89 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using UnityEngine;
+
+public class HatManager : DestroyableSingleton<HatManager>
+{
+ public HatBehaviour NoneHat;
+
+ public List<PetBehaviour> AllPets = new List<PetBehaviour>();
+
+ public List<HatBehaviour> AllHats = new List<HatBehaviour>();
+
+ public List<SkinData> AllSkins = new List<SkinData>();
+
+ internal PetBehaviour GetPetById(uint petId)
+ {
+ if ((ulong)petId >= (ulong)((long)this.AllPets.Count))
+ {
+ return this.AllPets[0];
+ }
+ return this.AllPets[(int)petId];
+ }
+
+ public uint GetIdFromPet(PetBehaviour pet)
+ {
+ return (uint)this.AllPets.FindIndex((PetBehaviour p) => p.idleClip == pet.idleClip);
+ }
+
+ public PetBehaviour[] GetUnlockedPets()
+ {
+ return (from h in this.AllPets
+ where h.Free || SaveManager.GetPurchase(h.ProductId)
+ select h).ToArray<PetBehaviour>();
+ }
+
+ public HatBehaviour GetHatById(uint hatId)
+ {
+ if ((ulong)hatId >= (ulong)((long)this.AllHats.Count))
+ {
+ return this.NoneHat;
+ }
+ return this.AllHats[(int)hatId];
+ }
+
+ public HatBehaviour[] GetUnlockedHats()
+ {
+ return (from h in this.AllHats
+ where h.LimitedMonth == 0 || SaveManager.GetPurchase(h.ProductId)
+ select h into o
+ orderby o.Order descending, o.name
+ select o).ToArray<HatBehaviour>();
+ }
+
+ public uint GetIdFromHat(HatBehaviour hat)
+ {
+ return (uint)this.AllHats.IndexOf(hat);
+ }
+
+ public SkinData[] GetUnlockedSkins()
+ {
+ return (from o in this.AllSkins
+ orderby o.Order descending, o.name
+ select o).ToArray<SkinData>();
+ }
+
+ public uint GetIdFromSkin(SkinData skin)
+ {
+ return (uint)this.AllSkins.IndexOf(skin);
+ }
+
+ internal SkinData GetSkinById(uint skinId)
+ {
+ if ((ulong)skinId >= (ulong)((long)this.AllSkins.Count))
+ {
+ return this.AllSkins[0];
+ }
+ return this.AllSkins[(int)skinId];
+ }
+
+ internal void SetSkin(SpriteRenderer skinRend, uint skinId)
+ {
+ SkinData skinById = this.GetSkinById(skinId);
+ if (skinById)
+ {
+ skinRend.sprite = skinById.IdleFrame;
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/HatsTab.cs b/Client/Assembly-CSharp/HatsTab.cs
new file mode 100644
index 0000000..10f7b3a
--- /dev/null
+++ b/Client/Assembly-CSharp/HatsTab.cs
@@ -0,0 +1,83 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class HatsTab : MonoBehaviour
+{
+ public ColorChip ColorTabPrefab;
+
+ public SpriteRenderer DemoImage;
+
+ public SpriteRenderer HatImage;
+
+ public SpriteRenderer SkinImage;
+
+ public SpriteRenderer PetImage;
+
+ public FloatRange XRange = new FloatRange(1.5f, 3f);
+
+ public float YStart = 0.8f;
+
+ public float YOffset = 0.8f;
+
+ public int NumPerRow = 4;
+
+ public Scroller scroller;
+
+ private List<ColorChip> ColorChips = new List<ColorChip>();
+
+ public void OnEnable()
+ {
+ PlayerControl.SetPlayerMaterialColors((int)PlayerControl.LocalPlayer.Data.ColorId, this.DemoImage);
+ PlayerControl.SetHatImage(SaveManager.LastHat, this.HatImage);
+ PlayerControl.SetSkinImage(SaveManager.LastSkin, this.SkinImage);
+ PlayerControl.SetPetImage(SaveManager.LastPet, (int)PlayerControl.LocalPlayer.Data.ColorId, this.PetImage);
+ HatBehaviour[] unlockedHats = DestroyableSingleton<HatManager>.Instance.GetUnlockedHats();
+ for (int i = 0; i < unlockedHats.Length; i++)
+ {
+ HatBehaviour hat = unlockedHats[i];
+ float x = this.XRange.Lerp((float)(i % this.NumPerRow) / ((float)this.NumPerRow - 1f));
+ float y = this.YStart - (float)(i / this.NumPerRow) * this.YOffset;
+ ColorChip colorChip = UnityEngine.Object.Instantiate<ColorChip>(this.ColorTabPrefab, this.scroller.Inner);
+ colorChip.transform.localPosition = new Vector3(x, y, -1f);
+ colorChip.Button.OnClick.AddListener(delegate()
+ {
+ this.SelectHat(hat);
+ });
+ colorChip.Inner.sprite = hat.MainImage;
+ this.ColorChips.Add(colorChip);
+ }
+ this.scroller.YBounds.max = -(this.YStart - (float)(unlockedHats.Length / this.NumPerRow) * this.YOffset) - 3f;
+ }
+
+ public void OnDisable()
+ {
+ for (int i = 0; i < this.ColorChips.Count; i++)
+ {
+ UnityEngine.Object.Destroy(this.ColorChips[i].gameObject);
+ }
+ this.ColorChips.Clear();
+ }
+
+ public void Update()
+ {
+ PlayerControl.SetPlayerMaterialColors((int)PlayerControl.LocalPlayer.Data.ColorId, this.DemoImage);
+ HatBehaviour hatById = DestroyableSingleton<HatManager>.Instance.GetHatById(SaveManager.LastHat);
+ for (int i = 0; i < this.ColorChips.Count; i++)
+ {
+ ColorChip colorChip = this.ColorChips[i];
+ colorChip.InUseForeground.SetActive(hatById.MainImage == colorChip.Inner.sprite);
+ }
+ }
+
+ private void SelectHat(HatBehaviour hat)
+ {
+ uint idFromHat = DestroyableSingleton<HatManager>.Instance.GetIdFromHat(hat);
+ SaveManager.LastHat = idFromHat;
+ PlayerControl.SetHatImage(idFromHat, this.HatImage);
+ if (PlayerControl.LocalPlayer)
+ {
+ PlayerControl.LocalPlayer.RpcSetHat(idFromHat);
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/HorizontalGauge.cs b/Client/Assembly-CSharp/HorizontalGauge.cs
new file mode 100644
index 0000000..2995903
--- /dev/null
+++ b/Client/Assembly-CSharp/HorizontalGauge.cs
@@ -0,0 +1,26 @@
+using System;
+using UnityEngine;
+
+public class HorizontalGauge : MonoBehaviour
+{
+ public float Value = 0.5f;
+
+ public float MaxValue = 1f;
+
+ public float maskScale = 1f;
+
+ public SpriteMask Mask;
+
+ private float lastValue = float.MinValue;
+
+ public void Update()
+ {
+ if (this.MaxValue != 0f && this.lastValue != this.Value)
+ {
+ this.lastValue = this.Value;
+ float num = this.lastValue / this.MaxValue * this.maskScale;
+ this.Mask.transform.localScale = new Vector3(num, 1f, 1f);
+ this.Mask.transform.localPosition = new Vector3(-this.Mask.sprite.bounds.size.x * (this.maskScale - num) / 2f, 0f, 0f);
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/HostGameButton.cs b/Client/Assembly-CSharp/HostGameButton.cs
new file mode 100644
index 0000000..486dc8e
--- /dev/null
+++ b/Client/Assembly-CSharp/HostGameButton.cs
@@ -0,0 +1,135 @@
+using System;
+using System.Collections;
+using InnerNet;
+using PowerTools;
+using UnityEngine;
+
+public class HostGameButton : MonoBehaviour, IConnectButton
+{
+ public AudioClip IntroMusic;
+
+ public string targetScene;
+
+ public SpriteRenderer FillScreen;
+
+ public SpriteAnim connectIcon;
+
+ public AnimationClip connectClip;
+
+ public GameModes GameMode;
+
+ public void Start()
+ {
+ if (DestroyableSingleton<MatchMaker>.InstanceExists)
+ {
+ DestroyableSingleton<MatchMaker>.Instance.NotConnecting();
+ }
+ }
+
+ public void OnClick()
+ {
+ if (this.GameMode == GameModes.FreePlay)
+ {
+ if (!NameTextBehaviour.IsValidName(SaveManager.PlayerName))
+ {
+ SaveManager.PlayerName = "Player";
+ }
+ }
+ else
+ {
+ if (NameTextBehaviour.Instance.ShakeIfInvalid())
+ {
+ return;
+ }
+ if (StatsManager.Instance.AmBanned)
+ {
+ AmongUsClient.Instance.LastDisconnectReason = DisconnectReasons.IntentionalLeaving;
+ DestroyableSingleton<DisconnectPopup>.Instance.Show();
+ return;
+ }
+ if (!DestroyableSingleton<MatchMaker>.Instance.Connecting(this))
+ {
+ return;
+ }
+ }
+ base.StartCoroutine(this.CoStartGame());
+ }
+
+ public void StartIcon()
+ {
+ if (!this.connectIcon)
+ {
+ return;
+ }
+ this.connectIcon.Play(this.connectClip, 1f);
+ }
+
+ public void StopIcon()
+ {
+ if (!this.connectIcon)
+ {
+ return;
+ }
+ this.connectIcon.Stop();
+ this.connectIcon.GetComponent<SpriteRenderer>().sprite = null;
+ }
+
+ private IEnumerator CoStartGame()
+ {
+ try
+ {
+ SoundManager.Instance.StopAllSound();
+ AmongUsClient.Instance.GameMode = this.GameMode;
+ switch (this.GameMode)
+ {
+ case GameModes.LocalGame:
+ DestroyableSingleton<InnerNetServer>.Instance.StartAsServer();
+ AmongUsClient.Instance.SetEndpoint("127.0.0.1", 22023);
+ AmongUsClient.Instance.MainMenuScene = "MatchMaking";
+ break;
+ case GameModes.OnlineGame:
+ AmongUsClient.Instance.SetEndpoint(DestroyableSingleton<ServerManager>.Instance.OnlineNetAddress, 22023);
+ AmongUsClient.Instance.MainMenuScene = "MMOnline";
+ break;
+ case GameModes.FreePlay:
+ DestroyableSingleton<InnerNetServer>.Instance.StartAsServer();
+ AmongUsClient.Instance.SetEndpoint("127.0.0.1", 22023);
+ AmongUsClient.Instance.MainMenuScene = "MainMenu";
+ break;
+ }
+ }
+ catch (Exception ex)
+ {
+ DestroyableSingleton<DisconnectPopup>.Instance.ShowCustom(ex.Message);
+ DestroyableSingleton<MatchMaker>.Instance.NotConnecting();
+ yield break;
+ }
+ yield return new WaitForSeconds(0.1f);
+ if (this.FillScreen)
+ {
+ SoundManager.Instance.CrossFadeSound("MainBG", null, 0.5f, 1.5f);
+ this.FillScreen.gameObject.SetActive(true);
+ for (float time = 0f; time < 0.25f; time += Time.deltaTime)
+ {
+ this.FillScreen.color = Color.Lerp(Color.clear, Color.black, time / 0.25f);
+ yield return null;
+ }
+ this.FillScreen.color = Color.black;
+ }
+ AmongUsClient.Instance.OnlineScene = this.targetScene;
+ AmongUsClient.Instance.Connect(MatchMakerModes.HostAndClient);
+ yield return AmongUsClient.Instance.WaitForConnectionOrFail();
+ DestroyableSingleton<MatchMaker>.Instance.NotConnecting();
+ if (AmongUsClient.Instance.mode == MatchMakerModes.None && this.FillScreen)
+ {
+ SoundManager.Instance.CrossFadeSound("MainBG", this.IntroMusic, 0.5f, 1.5f);
+ for (float time = 0f; time < 0.25f; time += Time.deltaTime)
+ {
+ this.FillScreen.color = Color.Lerp(Color.black, Color.clear, time / 0.25f);
+ yield return null;
+ }
+ this.FillScreen.color = Color.clear;
+ }
+ yield break;
+ }
+}
diff --git a/Client/Assembly-CSharp/HowToPlayController.cs b/Client/Assembly-CSharp/HowToPlayController.cs
new file mode 100644
index 0000000..2274478
--- /dev/null
+++ b/Client/Assembly-CSharp/HowToPlayController.cs
@@ -0,0 +1,67 @@
+using System;
+using UnityEngine;
+using UnityEngine.SceneManagement;
+
+public class HowToPlayController : MonoBehaviour
+{
+ public Transform DotParent;
+
+ public SpriteRenderer leftButton;
+
+ public SpriteRenderer rightButton;
+
+ public SceneController PCMove;
+
+ public SceneController[] Scenes;
+
+ public int SceneNum;
+
+ public void Start()
+ {
+ this.Scenes[2] = this.PCMove;
+ this.PCMove.gameObject.SetActive(false);
+ for (int i = 1; i < this.Scenes.Length; i++)
+ {
+ this.Scenes[i].gameObject.SetActive(false);
+ }
+ for (int j = 0; j < this.DotParent.childCount; j++)
+ {
+ this.DotParent.GetChild(j).localScale = Vector3.one;
+ }
+ this.ChangeScene(0);
+ }
+
+ public void Update()
+ {
+ if (Input.GetKeyUp(KeyCode.Escape))
+ {
+ this.Close();
+ }
+ }
+
+ public void NextScene()
+ {
+ this.ChangeScene(1);
+ }
+
+ public void PreviousScene()
+ {
+ this.ChangeScene(-1);
+ }
+
+ public void Close()
+ {
+ SceneManager.LoadScene("MainMenu");
+ }
+
+ private void ChangeScene(int del)
+ {
+ this.Scenes[this.SceneNum].gameObject.SetActive(false);
+ this.DotParent.GetChild(this.SceneNum).localScale = Vector3.one;
+ this.SceneNum = Mathf.Clamp(this.SceneNum + del, 0, this.Scenes.Length - 1);
+ this.Scenes[this.SceneNum].gameObject.SetActive(true);
+ this.DotParent.GetChild(this.SceneNum).localScale = new Vector3(1.5f, 1.5f, 1.5f);
+ this.leftButton.gameObject.SetActive(this.SceneNum > 0);
+ this.rightButton.gameObject.SetActive(this.SceneNum < this.Scenes.Length - 1);
+ }
+}
diff --git a/Client/Assembly-CSharp/HudManager.cs b/Client/Assembly-CSharp/HudManager.cs
new file mode 100644
index 0000000..d3905ea
--- /dev/null
+++ b/Client/Assembly-CSharp/HudManager.cs
@@ -0,0 +1,312 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Text;
+using InnerNet;
+using UnityEngine;
+
+public class HudManager : DestroyableSingleton<HudManager>
+{
+ public Coroutine ReactorFlash { get; set; }
+
+ public Coroutine OxyFlash { get; set; }
+
+ public MeetingHud MeetingPrefab;
+
+ public KillButtonManager KillButton;
+
+ public UseButtonManager UseButton;
+
+ public ReportButtonManager ReportButton;
+
+ public TextRenderer GameSettings;
+
+ public GameObject TaskStuff;
+
+ public ChatController Chat;
+
+ public DialogueBox Dialogue;
+
+ public TextRenderer TaskText;
+
+ public Transform TaskCompleteOverlay;
+
+ private float taskDirtyTimer;
+
+ public MeshRenderer ShadowQuad;
+
+ public SpriteRenderer FullScreen;
+
+ public SpriteRenderer MapButton;
+
+ public KillOverlay KillOverlay;
+
+ public IVirtualJoystick joystick;
+
+ public MonoBehaviour[] Joysticks;
+
+ public DiscussBehaviour discussEmblem;
+
+ public ShhhBehaviour shhhEmblem;
+
+ public IntroCutscene IntroPrefab;
+
+ public OptionsMenuBehaviour GameMenu;
+
+ public NotificationPopper Notifier;
+
+ public RoomTracker roomTracker;
+
+ public AudioClip SabotageSound;
+
+ public AudioClip TaskCompleteSound;
+
+ public AudioClip TaskUpdateSound;
+
+ private StringBuilder tasksString = new StringBuilder();
+
+ public void Start()
+ {
+ this.SetTouchType(SaveManager.TouchConfig);
+ }
+
+ public void ShowTaskComplete()
+ {
+ base.StartCoroutine(this.CoTaskComplete());
+ }
+
+ private IEnumerator CoTaskComplete()
+ {
+ if (Constants.ShouldPlaySfx())
+ {
+ SoundManager.Instance.PlaySound(this.TaskCompleteSound, false, 1f);
+ }
+ this.TaskCompleteOverlay.gameObject.SetActive(true);
+ yield return Effects.Slide2D(this.TaskCompleteOverlay, new Vector2(0f, -8f), Vector2.zero, 0.25f);
+ for (float time = 0f; time < 0.75f; time += Time.deltaTime)
+ {
+ yield return null;
+ }
+ yield return Effects.Slide2D(this.TaskCompleteOverlay, Vector2.zero, new Vector2(0f, 8f), 0.25f);
+ this.TaskCompleteOverlay.gameObject.SetActive(false);
+ yield break;
+ }
+
+ public void SetJoystickSize(float size)
+ {
+ if (this.joystick != null && this.joystick is VirtualJoystick)
+ {
+ VirtualJoystick virtualJoystick = (VirtualJoystick)this.joystick;
+ virtualJoystick.transform.localScale = new Vector3(size, size, 1f);
+ AspectPosition component = virtualJoystick.GetComponent<AspectPosition>();
+ float num = Mathf.Lerp(0.65f, 1.1f, FloatRange.ReverseLerp(size, 0.5f, 1.5f));
+ component.DistanceFromEdge = new Vector3(num, num, -10f);
+ component.AdjustPosition();
+ }
+ }
+
+ public void SetTouchType(int type)
+ {
+ if (this.joystick != null && !(this.joystick is KeyboardJoystick))
+ {
+ UnityEngine.Object.Destroy((this.joystick as MonoBehaviour).gameObject);
+ }
+ MonoBehaviour monoBehaviour = UnityEngine.Object.Instantiate<MonoBehaviour>(this.Joysticks[Mathf.Clamp(type + 1, 1, this.Joysticks.Length)]);
+ monoBehaviour.transform.SetParent(base.transform, false);
+ this.joystick = monoBehaviour.GetComponent<IVirtualJoystick>();
+ }
+
+ public void OpenMap()
+ {
+ this.ShowMap(delegate(MapBehaviour m)
+ {
+ m.ShowNormalMap();
+ });
+ }
+
+ public void ShowMap(Action<MapBehaviour> mapAction)
+ {
+ if (!ShipStatus.Instance)
+ {
+ return;
+ }
+ if (!MapBehaviour.Instance)
+ {
+ MapBehaviour.Instance = UnityEngine.Object.Instantiate<MapBehaviour>(ShipStatus.Instance.MapPrefab, base.transform);
+ MapBehaviour.Instance.gameObject.SetActive(false);
+ }
+ mapAction(MapBehaviour.Instance);
+ }
+
+ public void SetHudActive(bool isActive)
+ {
+ DestroyableSingleton<HudManager>.Instance.UseButton.gameObject.SetActive(isActive);
+ DestroyableSingleton<HudManager>.Instance.UseButton.Refresh();
+ DestroyableSingleton<HudManager>.Instance.ReportButton.gameObject.SetActive(isActive);
+ GameData.PlayerInfo data = PlayerControl.LocalPlayer.Data;
+ DestroyableSingleton<HudManager>.Instance.KillButton.gameObject.SetActive(isActive && data.IsImpostor && !data.IsDead);
+ DestroyableSingleton<HudManager>.Instance.TaskText.transform.parent.gameObject.SetActive(isActive);
+ }
+
+ public void FixedUpdate()
+ {
+ this.taskDirtyTimer += Time.fixedDeltaTime;
+ if (this.taskDirtyTimer > 0.25f)
+ {
+ this.taskDirtyTimer = 0f;
+ if (!PlayerControl.LocalPlayer)
+ {
+ this.TaskText.Text = string.Empty;
+ return;
+ }
+ GameData.PlayerInfo data = PlayerControl.LocalPlayer.Data;
+ if (data == null)
+ {
+ return;
+ }
+ bool isImpostor = data.IsImpostor;
+ this.tasksString.Clear();
+ if (PlayerControl.LocalPlayer.myTasks.Count == 0)
+ {
+ this.tasksString.Append("None");
+ }
+ else
+ {
+ for (int i = 0; i < PlayerControl.LocalPlayer.myTasks.Count; i++)
+ {
+ PlayerTask playerTask = PlayerControl.LocalPlayer.myTasks[i];
+ if (playerTask)
+ {
+ if (playerTask.TaskType == TaskTypes.FixComms && !isImpostor)
+ {
+ this.tasksString.Clear();
+ playerTask.AppendTaskText(this.tasksString);
+ break;
+ }
+ playerTask.AppendTaskText(this.tasksString);
+ }
+ }
+ this.tasksString.TrimEnd();
+ }
+ this.TaskText.Text = this.tasksString.ToString();
+ }
+ }
+
+ public IEnumerator ShowEmblem(bool shhh)
+ {
+ if (shhh)
+ {
+ this.shhhEmblem.gameObject.SetActive(true);
+ yield return this.shhhEmblem.PlayAnimation();
+ this.shhhEmblem.gameObject.SetActive(false);
+ }
+ else
+ {
+ this.discussEmblem.gameObject.SetActive(true);
+ yield return this.discussEmblem.PlayAnimation();
+ this.discussEmblem.gameObject.SetActive(false);
+ }
+ yield break;
+ }
+
+ public void StartReactorFlash()
+ {
+ if (this.ReactorFlash == null)
+ {
+ this.ReactorFlash = base.StartCoroutine(this.CoReactorFlash());
+ }
+ }
+
+ public void StartOxyFlash()
+ {
+ if (this.OxyFlash == null)
+ {
+ this.OxyFlash = base.StartCoroutine(this.CoReactorFlash());
+ }
+ }
+
+ public void ShowPopUp(string text)
+ {
+ this.Dialogue.Show(text);
+ }
+
+ public void StopReactorFlash()
+ {
+ if (this.ReactorFlash != null)
+ {
+ base.StopCoroutine(this.ReactorFlash);
+ this.FullScreen.enabled = false;
+ this.ReactorFlash = null;
+ }
+ }
+
+ public void StopOxyFlash()
+ {
+ if (this.OxyFlash != null)
+ {
+ base.StopCoroutine(this.OxyFlash);
+ this.FullScreen.enabled = false;
+ this.OxyFlash = null;
+ }
+ }
+
+ public IEnumerator CoFadeFullScreen(Color source, Color target, float duration = 0.2f)
+ {
+ if (this.FullScreen.enabled && this.FullScreen.color == target)
+ {
+ yield break;
+ }
+ this.FullScreen.enabled = true;
+ for (float t = 0f; t < duration; t += Time.deltaTime)
+ {
+ this.FullScreen.color = Color.Lerp(source, target, t / duration);
+ yield return null;
+ }
+ this.FullScreen.color = target;
+ if (target.a < 0.05f)
+ {
+ this.FullScreen.enabled = false;
+ }
+ yield break;
+ }
+
+ private IEnumerator CoReactorFlash()
+ {
+ WaitForSeconds wait = new WaitForSeconds(1f);
+ this.FullScreen.color = new Color(1f, 0f, 0f, 0.37254903f);
+ for (;;)
+ {
+ this.FullScreen.enabled = !this.FullScreen.enabled;
+ SoundManager.Instance.PlaySound(this.SabotageSound, false, 1f);
+ yield return wait;
+ }
+ yield break;
+ }
+
+ public IEnumerator CoShowIntro(List<PlayerControl> yourTeam)
+ {
+ DestroyableSingleton<HudManager>.Instance.FullScreen.transform.localPosition = new Vector3(0f, 0f, -250f);
+ yield return DestroyableSingleton<HudManager>.Instance.ShowEmblem(true);
+ IntroCutscene introCutscene = UnityEngine.Object.Instantiate<IntroCutscene>(this.IntroPrefab, base.transform);
+ yield return introCutscene.CoBegin(yourTeam, PlayerControl.LocalPlayer.Data.IsImpostor);
+ PlayerControl.LocalPlayer.SetKillTimer(10f);
+ ((SabotageSystemType)ShipStatus.Instance.Systems[SystemTypes.Sabotage]).ForceSabTime(10f);
+ yield return this.CoFadeFullScreen(Color.black, Color.clear, 0.2f);
+ DestroyableSingleton<HudManager>.Instance.FullScreen.transform.localPosition = new Vector3(0f, 0f, -500f);
+ yield break;
+ }
+
+ public void OpenMeetingRoom(PlayerControl reporter)
+ {
+ if (MeetingHud.Instance)
+ {
+ return;
+ }
+ Debug.Log("Opening meeting room: " + reporter);
+ ShipStatus.Instance.RepairSystem(SystemTypes.Reactor, PlayerControl.LocalPlayer, 16);
+ ShipStatus.Instance.RepairSystem(SystemTypes.LifeSupp, PlayerControl.LocalPlayer, 16);
+ MeetingHud.Instance = UnityEngine.Object.Instantiate<MeetingHud>(this.MeetingPrefab);
+ MeetingHud.Instance.ServerStart(reporter.PlayerId);
+ AmongUsClient.Instance.Spawn(MeetingHud.Instance, -2, SpawnFlags.None);
+ }
+}
diff --git a/Client/Assembly-CSharp/HudOverrideSystemType.cs b/Client/Assembly-CSharp/HudOverrideSystemType.cs
new file mode 100644
index 0000000..82558cb
--- /dev/null
+++ b/Client/Assembly-CSharp/HudOverrideSystemType.cs
@@ -0,0 +1,40 @@
+using System;
+using Hazel;
+
+internal class HudOverrideSystemType : ISystemType, IActivatable
+{
+ public bool IsActive { get; private set; }
+
+ public const byte DamageBit = 128;
+
+ public const byte TaskMask = 127;
+
+ public bool Detoriorate(float deltaTime)
+ {
+ if (this.IsActive && !PlayerTask.PlayerHasHudTask(PlayerControl.LocalPlayer))
+ {
+ PlayerControl.LocalPlayer.AddSystemTask(SystemTypes.Comms);
+ }
+ return false;
+ }
+
+ public void RepairDamage(PlayerControl player, byte amount)
+ {
+ if ((amount & 128) > 0)
+ {
+ this.IsActive = true;
+ return;
+ }
+ this.IsActive = false;
+ }
+
+ public void Serialize(MessageWriter writer, bool initialState)
+ {
+ writer.Write(this.IsActive);
+ }
+
+ public void Deserialize(MessageReader reader, bool initialState)
+ {
+ this.IsActive = reader.ReadBoolean();
+ }
+}
diff --git a/Client/Assembly-CSharp/HudOverrideTask.cs b/Client/Assembly-CSharp/HudOverrideTask.cs
new file mode 100644
index 0000000..eb47b87
--- /dev/null
+++ b/Client/Assembly-CSharp/HudOverrideTask.cs
@@ -0,0 +1,82 @@
+using System;
+using System.Linq;
+using System.Text;
+using UnityEngine;
+
+public class HudOverrideTask : SabotageTask
+{
+ public override int TaskStep
+ {
+ get
+ {
+ if (!this.isComplete)
+ {
+ return 0;
+ }
+ return 1;
+ }
+ }
+
+ public override bool IsComplete
+ {
+ get
+ {
+ return this.isComplete;
+ }
+ }
+
+ private bool isComplete;
+
+ private HudOverrideSystemType system;
+
+ private bool even;
+
+ public override void Initialize()
+ {
+ ShipStatus instance = ShipStatus.Instance;
+ this.system = (instance.Systems[SystemTypes.Comms] as HudOverrideSystemType);
+ base.SetupArrows();
+ }
+
+ private void FixedUpdate()
+ {
+ if (this.isComplete)
+ {
+ return;
+ }
+ if (!this.system.IsActive)
+ {
+ this.Complete();
+ }
+ }
+
+ public override bool ValidConsole(global::Console console)
+ {
+ return console.TaskTypes.Contains(TaskTypes.FixComms);
+ }
+
+ public override void Complete()
+ {
+ this.isComplete = true;
+ PlayerControl.LocalPlayer.RemoveTask(this);
+ if (this.didContribute)
+ {
+ StatsManager instance = StatsManager.Instance;
+ uint sabsFixed = instance.SabsFixed;
+ instance.SabsFixed = sabsFixed + 1U;
+ }
+ }
+
+ public override void AppendTaskText(StringBuilder sb)
+ {
+ this.even = !this.even;
+ Color color = this.even ? Color.yellow : Color.red;
+ sb.Append(color.ToTextColor());
+ sb.Append(DestroyableSingleton<TranslationController>.Instance.GetString(TaskTypes.FixComms));
+ sb.Append("[]");
+ for (int i = 0; i < this.Arrows.Length; i++)
+ {
+ this.Arrows[i].image.color = color;
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/IActivatable.cs b/Client/Assembly-CSharp/IActivatable.cs
new file mode 100644
index 0000000..fd4ecbf
--- /dev/null
+++ b/Client/Assembly-CSharp/IActivatable.cs
@@ -0,0 +1,6 @@
+using System;
+
+public interface IActivatable
+{
+ bool IsActive { get; }
+}
diff --git a/Client/Assembly-CSharp/IBuyable.cs b/Client/Assembly-CSharp/IBuyable.cs
new file mode 100644
index 0000000..b19fbb4
--- /dev/null
+++ b/Client/Assembly-CSharp/IBuyable.cs
@@ -0,0 +1,6 @@
+using System;
+
+public interface IBuyable
+{
+ string ProdId { get; }
+}
diff --git a/Client/Assembly-CSharp/IBytesSerializable.cs b/Client/Assembly-CSharp/IBytesSerializable.cs
new file mode 100644
index 0000000..e256d7e
--- /dev/null
+++ b/Client/Assembly-CSharp/IBytesSerializable.cs
@@ -0,0 +1,6 @@
+using System;
+
+public interface IBytesSerializable
+{
+ byte[] ToBytes();
+}
diff --git a/Client/Assembly-CSharp/IConnectButton.cs b/Client/Assembly-CSharp/IConnectButton.cs
new file mode 100644
index 0000000..5f2848a
--- /dev/null
+++ b/Client/Assembly-CSharp/IConnectButton.cs
@@ -0,0 +1,8 @@
+using System;
+
+public interface IConnectButton
+{
+ void StartIcon();
+
+ void StopIcon();
+}
diff --git a/Client/Assembly-CSharp/IDisconnectHandler.cs b/Client/Assembly-CSharp/IDisconnectHandler.cs
new file mode 100644
index 0000000..c2482fe
--- /dev/null
+++ b/Client/Assembly-CSharp/IDisconnectHandler.cs
@@ -0,0 +1,9 @@
+using System;
+using InnerNet;
+
+public interface IDisconnectHandler
+{
+ void HandleDisconnect(PlayerControl pc, DisconnectReasons reason);
+
+ void HandleDisconnect();
+}
diff --git a/Client/Assembly-CSharp/IFocusHolder.cs b/Client/Assembly-CSharp/IFocusHolder.cs
new file mode 100644
index 0000000..1342fa8
--- /dev/null
+++ b/Client/Assembly-CSharp/IFocusHolder.cs
@@ -0,0 +1,11 @@
+using System;
+using UnityEngine;
+
+public interface IFocusHolder
+{
+ void GiveFocus();
+
+ void LoseFocus();
+
+ bool CheckCollision(Vector2 pt);
+}
diff --git a/Client/Assembly-CSharp/IGameListHandler.cs b/Client/Assembly-CSharp/IGameListHandler.cs
new file mode 100644
index 0000000..4be55da
--- /dev/null
+++ b/Client/Assembly-CSharp/IGameListHandler.cs
@@ -0,0 +1,8 @@
+using System;
+using System.Collections.Generic;
+using InnerNet;
+
+public interface IGameListHandler
+{
+ void HandleList(int totalGames, List<GameListing> availableGames);
+}
diff --git a/Client/Assembly-CSharp/ILocationActivate.cs b/Client/Assembly-CSharp/ILocationActivate.cs
new file mode 100644
index 0000000..2d9bb88
--- /dev/null
+++ b/Client/Assembly-CSharp/ILocationActivate.cs
@@ -0,0 +1,6 @@
+using System;
+
+internal interface ILocationActivate
+{
+ void LocationUse(PlayerControl pc);
+}
diff --git a/Client/Assembly-CSharp/IObjectPool.cs b/Client/Assembly-CSharp/IObjectPool.cs
new file mode 100644
index 0000000..312a917
--- /dev/null
+++ b/Client/Assembly-CSharp/IObjectPool.cs
@@ -0,0 +1,13 @@
+using System;
+using UnityEngine;
+
+public abstract class IObjectPool : MonoBehaviour
+{
+ public abstract int InUse { get; }
+
+ public abstract int NotInUse { get; }
+
+ public abstract T Get<T>() where T : PoolableBehavior;
+
+ public abstract void Reclaim(PoolableBehavior obj);
+}
diff --git a/Client/Assembly-CSharp/ISoundPlayer.cs b/Client/Assembly-CSharp/ISoundPlayer.cs
new file mode 100644
index 0000000..0b5d3ca
--- /dev/null
+++ b/Client/Assembly-CSharp/ISoundPlayer.cs
@@ -0,0 +1,11 @@
+using System;
+using UnityEngine;
+
+public interface ISoundPlayer
+{
+ string Name { get; set; }
+
+ AudioSource Player { get; set; }
+
+ void Update(float dt);
+}
diff --git a/Client/Assembly-CSharp/ISystemType.cs b/Client/Assembly-CSharp/ISystemType.cs
new file mode 100644
index 0000000..6e6d4fd
--- /dev/null
+++ b/Client/Assembly-CSharp/ISystemType.cs
@@ -0,0 +1,15 @@
+using System;
+using Hazel;
+
+// 需要同步的内容,比如门DoorsSystemType
+
+public interface ISystemType
+{
+ bool Detoriorate(float deltaTime);
+
+ void RepairDamage(PlayerControl player, byte amount);
+
+ void Serialize(MessageWriter writer, bool initialState);
+
+ void Deserialize(MessageReader reader, bool initialState);
+}
diff --git a/Client/Assembly-CSharp/ITranslatedText.cs b/Client/Assembly-CSharp/ITranslatedText.cs
new file mode 100644
index 0000000..f6f1857
--- /dev/null
+++ b/Client/Assembly-CSharp/ITranslatedText.cs
@@ -0,0 +1,6 @@
+using System;
+
+public interface ITranslatedText
+{
+ void ResetText();
+}
diff --git a/Client/Assembly-CSharp/IUsable.cs b/Client/Assembly-CSharp/IUsable.cs
new file mode 100644
index 0000000..12053be
--- /dev/null
+++ b/Client/Assembly-CSharp/IUsable.cs
@@ -0,0 +1,14 @@
+using System;
+
+public interface IUsable
+{
+ float UsableDistance { get; }
+
+ float PercentCool { get; }
+
+ void SetOutline(bool on, bool mainTarget);
+
+ float CanUse(GameData.PlayerInfo pc, out bool canUse, out bool couldUse);
+
+ void Use();
+}
diff --git a/Client/Assembly-CSharp/IVirtualJoystick.cs b/Client/Assembly-CSharp/IVirtualJoystick.cs
new file mode 100644
index 0000000..fdfeef8
--- /dev/null
+++ b/Client/Assembly-CSharp/IVirtualJoystick.cs
@@ -0,0 +1,7 @@
+using System;
+using UnityEngine;
+
+public interface IVirtualJoystick
+{
+ Vector2 Delta { get; }
+}
diff --git a/Client/Assembly-CSharp/ImageData.cs b/Client/Assembly-CSharp/ImageData.cs
new file mode 100644
index 0000000..762189b
--- /dev/null
+++ b/Client/Assembly-CSharp/ImageData.cs
@@ -0,0 +1,10 @@
+using System;
+using UnityEngine;
+
+[Serializable]
+public struct ImageData
+{
+ public ImageNames Name;
+
+ public Sprite Sprite;
+}
diff --git a/Client/Assembly-CSharp/ImageNames.cs b/Client/Assembly-CSharp/ImageNames.cs
new file mode 100644
index 0000000..e70e8a8
--- /dev/null
+++ b/Client/Assembly-CSharp/ImageNames.cs
@@ -0,0 +1,12 @@
+using System;
+
+public enum ImageNames
+{
+ LocalButton,
+ OnlineButton,
+ HowToPlayButton,
+ FreeplayButton,
+ HostHeader,
+ PublicHeader,
+ PrivateHeader
+}
diff --git a/Client/Assembly-CSharp/ImageTranslator.cs b/Client/Assembly-CSharp/ImageTranslator.cs
new file mode 100644
index 0000000..7ea508b
--- /dev/null
+++ b/Client/Assembly-CSharp/ImageTranslator.cs
@@ -0,0 +1,24 @@
+using System;
+using UnityEngine;
+
+[RequireComponent(typeof(SpriteRenderer))]
+public class ImageTranslator : MonoBehaviour, ITranslatedText
+{
+ public ImageNames TargetImage;
+
+ public void ResetText()
+ {
+ base.GetComponent<SpriteRenderer>().sprite = DestroyableSingleton<TranslationController>.Instance.GetImage(this.TargetImage);
+ }
+
+ public void Start()
+ {
+ DestroyableSingleton<TranslationController>.Instance.ActiveTexts.Add(this);
+ this.ResetText();
+ }
+
+ public void OnDestroy()
+ {
+ DestroyableSingleton<TranslationController>.Instance.ActiveTexts.Remove(this);
+ }
+}
diff --git a/Client/Assembly-CSharp/ImportantTextTask.cs b/Client/Assembly-CSharp/ImportantTextTask.cs
new file mode 100644
index 0000000..7eb28b7
--- /dev/null
+++ b/Client/Assembly-CSharp/ImportantTextTask.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Text;
+
+public class ImportantTextTask : PlayerTask
+{
+ public override int TaskStep
+ {
+ get
+ {
+ return 0;
+ }
+ }
+
+ public override bool IsComplete
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ public string Text;
+
+ public override void Initialize()
+ {
+ }
+
+ public override bool ValidConsole(global::Console console)
+ {
+ return false;
+ }
+
+ public override void Complete()
+ {
+ }
+
+ public override void AppendTaskText(StringBuilder sb)
+ {
+ sb.AppendLine("[FF0000FF]" + this.Text + "[]");
+ }
+}
diff --git a/Client/Assembly-CSharp/InfectedOverlay.cs b/Client/Assembly-CSharp/InfectedOverlay.cs
new file mode 100644
index 0000000..53d7942
--- /dev/null
+++ b/Client/Assembly-CSharp/InfectedOverlay.cs
@@ -0,0 +1,51 @@
+using System;
+using UnityEngine;
+
+public class InfectedOverlay : MonoBehaviour
+{
+ public bool CanUseDoors
+ {
+ get
+ {
+ return !this.SabSystem.AnyActive;
+ }
+ }
+
+ public bool CanUseSpecial
+ {
+ get
+ {
+ return this.SabSystem.Timer <= 0f && !this.doors.IsActive && !this.SabSystem.AnyActive;
+ }
+ }
+
+ public MapRoom[] rooms;
+
+ private IActivatable doors;
+
+ private SabotageSystemType SabSystem;
+
+ public void Start()
+ {
+ for (int i = 0; i < this.rooms.Length; i++)
+ {
+ this.rooms[i].Parent = this;
+ }
+ this.SabSystem = (SabotageSystemType)ShipStatus.Instance.Systems[SystemTypes.Sabotage];
+ this.doors = (IActivatable)ShipStatus.Instance.Systems[SystemTypes.Doors];
+ }
+
+ private void FixedUpdate()
+ {
+ if (this.doors == null)
+ {
+ return;
+ }
+ float specialActive = this.doors.IsActive ? 1f : this.SabSystem.PercentCool;
+ for (int i = 0; i < this.rooms.Length; i++)
+ {
+ this.rooms[i].SetSpecialActive(specialActive);
+ this.rooms[i].OOBUpdate();
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/InnerNet/AlterGameTags.cs b/Client/Assembly-CSharp/InnerNet/AlterGameTags.cs
new file mode 100644
index 0000000..730126b
--- /dev/null
+++ b/Client/Assembly-CSharp/InnerNet/AlterGameTags.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace InnerNet
+{
+ public static class AlterGameTags
+ {
+ public const byte ChangePrivacy = 1;
+ }
+}
diff --git a/Client/Assembly-CSharp/InnerNet/ClientData.cs b/Client/Assembly-CSharp/InnerNet/ClientData.cs
new file mode 100644
index 0000000..780d6ae
--- /dev/null
+++ b/Client/Assembly-CSharp/InnerNet/ClientData.cs
@@ -0,0 +1,21 @@
+using System;
+
+namespace InnerNet
+{
+ [Serializable]
+ public class ClientData
+ {
+ public int Id;
+
+ public bool InScene;
+
+ public bool IsReady;
+
+ public PlayerControl Character;
+
+ public ClientData(int id)
+ {
+ this.Id = id;
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/InnerNet/DisconnectReasons.cs b/Client/Assembly-CSharp/InnerNet/DisconnectReasons.cs
new file mode 100644
index 0000000..1d9c4a6
--- /dev/null
+++ b/Client/Assembly-CSharp/InnerNet/DisconnectReasons.cs
@@ -0,0 +1,25 @@
+using System;
+
+namespace InnerNet
+{
+ public enum DisconnectReasons
+ {
+ ExitGame,
+ GameFull,
+ GameStarted,
+ GameNotFound,
+ IncorrectVersion = 5,
+ Banned,
+ Kicked,
+ Custom,
+ Destroy = 16,
+ Error,
+ IncorrectGame,
+ ServerRequest,
+ ServerFull,
+ IntentionalLeaving = 208,
+ FocusLostBackground = 207,
+ FocusLost = 209,
+ NewConnection
+ }
+}
diff --git a/Client/Assembly-CSharp/InnerNet/GameKeywords.cs b/Client/Assembly-CSharp/InnerNet/GameKeywords.cs
new file mode 100644
index 0000000..76eaabc
--- /dev/null
+++ b/Client/Assembly-CSharp/InnerNet/GameKeywords.cs
@@ -0,0 +1,16 @@
+using System;
+
+namespace InnerNet
+{
+ [Flags]
+ public enum GameKeywords : uint
+ {
+ All = 0U,
+ AllLanguages = 31U,
+ English = 1U,
+ Spanish = 2U,
+ Korean = 4U,
+ Russian = 8U,
+ Portuguese = 16U
+ }
+}
diff --git a/Client/Assembly-CSharp/InnerNet/GameListing.cs b/Client/Assembly-CSharp/InnerNet/GameListing.cs
new file mode 100644
index 0000000..d10ea34
--- /dev/null
+++ b/Client/Assembly-CSharp/InnerNet/GameListing.cs
@@ -0,0 +1,30 @@
+using System;
+
+namespace InnerNet
+{
+ [Serializable]
+ public struct GameListing
+ {
+ public int GameId;
+
+ public byte PlayerCount;
+
+ public byte ImpostorCount;
+
+ public byte MaxPlayers;
+
+ public int Age;
+
+ public string HostName;
+
+ public GameListing(int id, byte numImpostors, byte playerCount, byte maxPlayers, int age, string host)
+ {
+ this.GameId = id;
+ this.ImpostorCount = numImpostors;
+ this.PlayerCount = playerCount;
+ this.MaxPlayers = maxPlayers;
+ this.Age = age;
+ this.HostName = host;
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/InnerNet/GameStates.cs b/Client/Assembly-CSharp/InnerNet/GameStates.cs
new file mode 100644
index 0000000..812ffa2
--- /dev/null
+++ b/Client/Assembly-CSharp/InnerNet/GameStates.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace InnerNet
+{
+ public enum GameStates : byte
+ {
+ NotStarted,
+ Started,
+ Ended,
+ Destroyed
+ }
+}
diff --git a/Client/Assembly-CSharp/InnerNet/InnerDiscover.cs b/Client/Assembly-CSharp/InnerNet/InnerDiscover.cs
new file mode 100644
index 0000000..b596ef5
--- /dev/null
+++ b/Client/Assembly-CSharp/InnerNet/InnerDiscover.cs
@@ -0,0 +1,114 @@
+using System;
+using System.Collections;
+using System.Net.Sockets;
+using Hazel.Udp;
+using UnityEngine;
+
+namespace InnerNet
+{
+ public class InnerDiscover : DestroyableSingleton<InnerDiscover>
+ {
+ public event Action<BroadcastPacket> OnPacketGet;
+
+ private UdpBroadcastListener listener;
+
+ private UdpBroadcaster sender;
+
+ public int Port = 47777;
+
+ public float Interval = 1f;
+
+ public void StartAsServer(string data)
+ {
+ bool flag = this.sender == null;
+ if (flag)
+ {
+ this.sender = new UdpBroadcaster(this.Port);
+ }
+ this.sender.SetData(data);
+ if (flag)
+ {
+ base.StartCoroutine(this.RunServer());
+ }
+ }
+
+ private IEnumerator RunServer()
+ {
+ while (this.sender != null)
+ {
+ this.sender.Broadcast();
+ for (float timer = 0f; timer < this.Interval; timer += Time.deltaTime)
+ {
+ yield return null;
+ }
+ }
+ yield break;
+ }
+
+ public void StopServer()
+ {
+ if (this.sender != null)
+ {
+ this.sender.Dispose();
+ this.sender = null;
+ }
+ }
+
+ public void StartAsClient()
+ {
+ if (this.listener == null)
+ {
+ try
+ {
+ this.listener = new UdpBroadcastListener(this.Port);
+ this.listener.StartListen();
+ base.StartCoroutine(this.RunClient());
+ }
+ catch (SocketException)
+ {
+ AmongUsClient.Instance.LastDisconnectReason = DisconnectReasons.Custom;
+ AmongUsClient.Instance.LastCustomDisconnect = "Couldn't start local network listener. You may need to restart Among Us.";
+ DestroyableSingleton<DisconnectPopup>.Instance.Show();
+ }
+ }
+ }
+
+ private IEnumerator RunClient()
+ {
+ while (this.listener != null)
+ {
+ if (!this.listener.Running)
+ {
+ this.listener.StartListen();
+ }
+ BroadcastPacket[] packets = this.listener.GetPackets();
+ for (int i = 0; i < packets.Length; i++)
+ {
+ Action<BroadcastPacket> onPacketGet = this.OnPacketGet;
+ if (onPacketGet != null)
+ {
+ onPacketGet(packets[i]);
+ }
+ }
+ yield return null;
+ }
+ yield break;
+ }
+
+ public void StopClient()
+ {
+ if (this.listener != null)
+ {
+ this.listener.Dispose();
+ this.listener = null;
+ }
+ }
+
+ public override void OnDestroy()
+ {
+ this.StopServer();
+ this.StopClient();
+ base.OnDestroy();
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/InnerNet/InnerNetClient.cs b/Client/Assembly-CSharp/InnerNet/InnerNetClient.cs
new file mode 100644
index 0000000..7cff87c
--- /dev/null
+++ b/Client/Assembly-CSharp/InnerNet/InnerNetClient.cs
@@ -0,0 +1,1726 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Threading;
+using Assets.CoreScripts;
+using Hazel;
+using Hazel.Udp;
+using UnityEngine;
+using UnityEngine.SceneManagement;
+
+namespace InnerNet
+{
+ public abstract class InnerNetClient : MonoBehaviour
+ {
+ private bool AmConnected
+ {
+ get
+ {
+ return this.connection != null;
+ }
+ }
+
+ public int Ping
+ {
+ get
+ {
+ if (this.connection == null)
+ {
+ return 0;
+ }
+ return (int)this.connection.AveragePingMs;
+ }
+ }
+
+ public bool AmHost
+ {
+ get
+ {
+ return this.HostId == this.ClientId;
+ }
+ }
+
+ public bool AmClient
+ {
+ get
+ {
+ return this.ClientId > 0;
+ }
+ }
+
+ public bool IsGamePublic { get; private set; }
+
+ public bool IsGameStarted
+ {
+ get
+ {
+ return this.GameState == InnerNetClient.GameStates.Started;
+ }
+ }
+
+ public bool IsGameOver
+ {
+ get
+ {
+ return this.GameState == InnerNetClient.GameStates.Ended;
+ }
+ }
+
+ private static readonly DisconnectReasons[] disconnectReasons = new DisconnectReasons[]
+ {
+ DisconnectReasons.Error,
+ DisconnectReasons.GameFull,
+ DisconnectReasons.GameStarted,
+ DisconnectReasons.GameNotFound,
+ DisconnectReasons.IncorrectVersion,
+ DisconnectReasons.Banned,
+ DisconnectReasons.Kicked,
+ DisconnectReasons.ServerFull,
+ DisconnectReasons.Custom
+ };
+
+ public const int NoClientId = -1;
+
+ private string networkAddress = "127.0.0.1";
+
+ private int networkPort;
+
+ private UdpClientConnection connection;
+
+ public MatchMakerModes mode;
+
+ public int GameId = 32;
+
+ public int HostId;
+
+ public int ClientId = -1;
+
+ public List<ClientData> allClients = new List<ClientData>();
+
+ public DisconnectReasons LastDisconnectReason;
+
+ public string LastCustomDisconnect;
+
+ private readonly List<Action> PreSpawnDispatcher = new List<Action>();
+
+ //c 网络消息队列,网络线程写入,主线程调用
+ private readonly List<Action> Dispatcher = new List<Action>();
+
+ public InnerNetClient.GameStates GameState;
+
+ private List<Action> TempQueue = new List<Action>();
+
+ private volatile bool appPaused;
+
+ public const int CurrentClient = -3;
+
+ public const int InvalidClient = -2;
+
+ internal const byte DataFlag = 1;
+
+ internal const byte RpcFlag = 2;
+
+ internal const byte SpawnFlag = 4;
+
+ internal const byte DespawnFlag = 5;
+
+ internal const byte SceneChangeFlag = 6;
+
+ internal const byte ReadyFlag = 7;
+
+ internal const byte ChangeSettingsFlag = 8;
+
+ // 每次发送数据的间隔,每过0.1s发送一次
+ public float MinSendInterval = 0.1f;
+
+ private uint NetIdCnt = 1U;
+
+ private float timer;
+
+ public InnerNetObject[] SpawnableObjects;
+
+ private bool InOnlineScene;
+
+ private HashSet<uint> DestroyedObjects = new HashSet<uint>();
+
+ // 所有要同步的数据,包括InnerNetObject的所有派生类,场景内所有的对象的数据
+ public List<InnerNetObject> allObjects = new List<InnerNetObject>();
+
+ private Dictionary<uint, InnerNetObject> allObjectsFast = new Dictionary<uint, InnerNetObject>();
+
+ private MessageWriter[] Streams;
+
+ public enum GameStates
+ {
+ NotJoined,
+ Joined,
+ Started,
+ Ended
+ }
+
+ public void SetEndpoint(string addr, ushort port)
+ {
+ this.networkAddress = addr;
+ this.networkPort = (int)port;
+ }
+
+ public virtual void Start()
+ {
+ SceneManager.activeSceneChanged += delegate(Scene oldScene, Scene scene)
+ {
+ this.SendSceneChange(scene.name);
+ };
+ this.ClientId = -1;
+ this.GameId = 32;
+ }
+
+ private void SendOrDisconnect(MessageWriter msg)
+ {
+ try
+ {
+ this.connection.Send(msg);
+ }
+ catch
+ {
+ this.EnqueueDisconnect(DisconnectReasons.Error, "Failed to send message");
+ }
+ }
+
+ public ClientData GetHost()
+ {
+ List<ClientData> obj = this.allClients;
+ lock (obj)
+ {
+ for (int i = 0; i < this.allClients.Count; i++)
+ {
+ ClientData clientData = this.allClients[i];
+ if (clientData.Id == this.HostId)
+ {
+ return clientData;
+ }
+ }
+ }
+ return null;
+ }
+
+ public int GetClientIdFromCharacter(InnerNetObject character)
+ {
+ if (!character)
+ {
+ return -1;
+ }
+ List<ClientData> obj = this.allClients;
+ lock (obj)
+ {
+ for (int i = 0; i < this.allClients.Count; i++)
+ {
+ ClientData clientData = this.allClients[i];
+ if (clientData.Character == character)
+ {
+ return clientData.Id;
+ }
+ }
+ }
+ return -1;
+ }
+
+ public virtual void OnDestroy()
+ {
+ if (this.AmConnected)
+ {
+ this.DisconnectInternal(DisconnectReasons.Destroy, null);
+ }
+ }
+
+ public IEnumerator CoConnect()
+ {
+ if (this.AmConnected)
+ {
+ yield break;
+ }
+ DestroyableSingleton<DisconnectPopup>.Instance.Close();
+ this.LastDisconnectReason = DisconnectReasons.ExitGame;
+ this.NetIdCnt = 1U;
+ this.DestroyedObjects.Clear();
+ if (this.Streams == null)
+ {
+ this.Streams = new MessageWriter[2];
+ for (int i = 0; i < this.Streams.Length; i++)
+ {
+ this.Streams[i] = MessageWriter.Get((SendOption)i);
+ }
+ }
+ for (int j = 0; j < this.Streams.Length; j++)
+ {
+ MessageWriter messageWriter = this.Streams[j];
+ messageWriter.Clear((SendOption)j);
+ messageWriter.StartMessage(5);
+ messageWriter.Write(this.GameId);
+ }
+ IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Parse(this.networkAddress), this.networkPort);
+ this.connection = new UdpClientConnection(remoteEndPoint, IPMode.IPv4);
+ this.connection.KeepAliveInterval = 1500;
+ this.connection.DisconnectTimeout = 7500;
+ this.connection.ResendPingMultiplier = 2f;
+ this.connection.DataReceived += this.OnMessageReceived; // 注册到网络线程的消息处理函数
+ this.connection.Disconnected += this.OnDisconnect; // 连接断开时的回调函数
+ this.connection.ConnectAsync(this.GetConnectionData(), 5000);
+
+ yield return this.WaitWithTimeout(() => this.connection == null || this.connection.State == ConnectionState.Connected);
+
+ yield break;
+ }
+
+ private void Connection_DataReceivedRaw(byte[] data)
+ {
+ Debug.Log("Client Got: " + string.Join(" ", from b in data
+ select b.ToString()));
+ }
+
+ private void Connection_DataSentRaw(byte[] data, int length)
+ {
+ Debug.Log("Client Sent: " + string.Join(" ", (from b in data
+ select b.ToString()).ToArray<string>(), 0, length));
+ }
+
+ public void Connect(MatchMakerModes mode)
+ {
+ base.StartCoroutine(this.CoConnect(mode));
+ }
+
+ private IEnumerator CoConnect(MatchMakerModes mode)
+ {
+ if (this.mode != MatchMakerModes.None)
+ {
+ this.DisconnectInternal(DisconnectReasons.NewConnection, null);
+ }
+ this.mode = mode;
+ yield return this.CoConnect();
+ if (!this.AmConnected)
+ {
+ yield break;
+ }
+ MatchMakerModes matchMakerModes = this.mode;
+ if (matchMakerModes == MatchMakerModes.Client)
+ {
+ this.JoinGame();
+ yield return this.WaitWithTimeout(() => this.ClientId >= 0);
+ bool amConnected = this.AmConnected;
+ yield break;
+ }
+ if (matchMakerModes != MatchMakerModes.HostAndClient)
+ {
+ yield break;
+ }
+ this.GameId = 0;
+ PlayerControl.GameOptions = SaveManager.GameHostOptions;
+ this.HostGame(PlayerControl.GameOptions);
+ yield return this.WaitWithTimeout(() => this.GameId != 0);
+ if (!this.AmConnected)
+ {
+ yield break;
+ }
+ this.JoinGame();
+ yield return this.WaitWithTimeout(() => this.ClientId >= 0);
+ bool amConnected2 = this.AmConnected;
+ yield break;
+ }
+
+ public IEnumerator WaitForConnectionOrFail()
+ {
+ while (this.AmConnected)
+ {
+ switch (this.mode)
+ {
+ case MatchMakerModes.None:
+ goto IL_5F;
+ case MatchMakerModes.Client:
+ if (this.ClientId >= 0)
+ {
+ yield break;
+ }
+ break;
+ case MatchMakerModes.HostAndClient:
+ if (this.GameId != 0 && this.ClientId >= 0)
+ {
+ yield break;
+ }
+ break;
+ default:
+ goto IL_5F;
+ }
+ yield return null;
+ continue;
+ IL_5F:
+ yield break;
+ }
+ yield break;
+ }
+
+ private IEnumerator WaitWithTimeout(Func<bool> success)
+ {
+ bool failed = true;
+ for (float timer = 0f; timer < 5f; timer += Time.deltaTime)
+ {
+ if (success())
+ {
+ failed = false;
+ break;
+ }
+ if (!this.AmConnected)
+ {
+ yield break;
+ }
+ yield return null;
+ }
+ if (failed)
+ {
+ this.DisconnectInternal(DisconnectReasons.Error, null);
+ }
+ yield break;
+ }
+
+ //c 执行从网络线程收到的回调Dispatcher
+ public void Update()
+ {
+ if (Input.GetKeyDown(KeyCode.Return) && (Input.GetKey(KeyCode.LeftAlt) || Input.GetKey(KeyCode.RightAlt)))
+ {
+ ResolutionManager.ToggleFullscreen();
+ }
+ this.TempQueue.Clear();
+ List<Action> obj = this.Dispatcher;
+ lock (obj)
+ {
+ this.TempQueue.AddAll(this.Dispatcher);
+ this.Dispatcher.Clear();
+ }
+ for (int i = 0; i < this.TempQueue.Count; i++)
+ {
+ Action action = this.TempQueue[i];
+ try
+ {
+ action();
+ }
+ catch (Exception exception)
+ {
+ Debug.LogException(exception);
+ }
+ }
+ if (this.InOnlineScene)
+ {
+ this.TempQueue.Clear();
+ obj = this.PreSpawnDispatcher;
+ lock (obj)
+ {
+ this.TempQueue.AddAll(this.PreSpawnDispatcher);
+ this.PreSpawnDispatcher.Clear();
+ }
+ for (int j = 0; j < this.TempQueue.Count; j++)
+ {
+ Action action2 = this.TempQueue[j];
+ try
+ {
+ action2();
+ }
+ catch (Exception exception2)
+ {
+ Debug.LogException(exception2);
+ }
+ }
+ }
+ }
+
+ private void OnDisconnect(object sender, DisconnectedEventArgs e)
+ {
+ if (!e.Reason.Contains("The remote sent a"))
+ {
+ this.LastCustomDisconnect = "You disconnected from the server.\r\n\r\n" + e.Reason;
+ this.EnqueueDisconnect(DisconnectReasons.Custom, e.Reason);
+ return;
+ }
+ this.EnqueueDisconnect(DisconnectReasons.Error, e.Reason);
+ }
+
+ public void HandleDisconnect(DisconnectReasons reason, string stringReason = null)
+ {
+ base.StopAllCoroutines();
+ DestroyableSingleton<Telemetry>.Instance.WriteDisconnect(this.LastDisconnectReason);
+ this.DisconnectInternal(reason, stringReason);
+ this.OnDisconnected();
+ }
+
+ protected void EnqueueDisconnect(DisconnectReasons reason, string stringReason = null)
+ {
+ UdpClientConnection udpClientConnection = this.connection;
+ List<Action> dispatcher = this.Dispatcher;
+ lock (dispatcher)
+ {
+ this.Dispatcher.Add(delegate
+ {
+ this.HandleDisconnect(reason, stringReason);
+ });
+ }
+ }
+
+ protected void DisconnectInternal(DisconnectReasons reason, string stringReason = null)
+ {
+ if (reason != DisconnectReasons.NewConnection && reason != DisconnectReasons.FocusLostBackground)
+ {
+ this.LastDisconnectReason = reason;
+ if (reason != DisconnectReasons.ExitGame && DestroyableSingleton<DisconnectPopup>.InstanceExists)
+ {
+ DestroyableSingleton<DisconnectPopup>.Instance.Show();
+ }
+ }
+ if (this.mode == MatchMakerModes.HostAndClient)
+ {
+ this.GameId = 0;
+ }
+ if (this.mode == MatchMakerModes.Client || this.mode == MatchMakerModes.HostAndClient)
+ {
+ this.ClientId = -1;
+ }
+ this.mode = MatchMakerModes.None;
+ this.GameState = InnerNetClient.GameStates.NotJoined;
+ UdpClientConnection udpClientConnection = this.connection;
+ this.connection = null;
+ if (udpClientConnection != null)
+ {
+ try
+ {
+ udpClientConnection.Dispose();
+ }
+ catch (Exception exception)
+ {
+ Debug.LogException(exception);
+ }
+ }
+ if (DestroyableSingleton<InnerNetServer>.InstanceExists)
+ {
+ DestroyableSingleton<InnerNetServer>.Instance.StopServer();
+ }
+ List<Action> obj = this.Dispatcher;
+ lock (obj)
+ {
+ this.Dispatcher.Clear();
+ }
+ obj = this.PreSpawnDispatcher;
+ lock (obj)
+ {
+ this.PreSpawnDispatcher.Clear();
+ }
+ if (reason != DisconnectReasons.Error)
+ {
+ this.TempQueue.Clear();
+ }
+ this.allObjects.Clear();
+ this.allClients.Clear();
+ this.allObjectsFast.Clear();
+ }
+
+ public void HostGame(IBytesSerializable settings)
+ {
+ this.IsGamePublic = false;
+ MessageWriter messageWriter = MessageWriter.Get(SendOption.Reliable);
+ messageWriter.StartMessage(0);
+ messageWriter.WriteBytesAndSize(settings.ToBytes());
+ messageWriter.EndMessage();
+ this.SendOrDisconnect(messageWriter);
+ messageWriter.Recycle();
+ Debug.Log("Client requesting new game.");
+ }
+
+ public void JoinGame()
+ {
+ this.ClientId = -1;
+ if (!this.AmConnected)
+ {
+ this.HandleDisconnect(DisconnectReasons.Error, null);
+ return;
+ }
+ Debug.Log("Client joining game: " + InnerNetClient.IntToGameName(this.GameId));
+ MessageWriter messageWriter = MessageWriter.Get(SendOption.Reliable);
+ messageWriter.StartMessage(1);
+ messageWriter.Write(this.GameId);
+ messageWriter.EndMessage();
+ this.SendOrDisconnect(messageWriter);
+ messageWriter.Recycle();
+ }
+
+ public bool CanBan()
+ {
+ return this.AmHost && !this.IsGameStarted;
+ }
+
+ public bool CanKick()
+ {
+ return this.IsGameStarted || this.AmHost;
+ }
+
+ public void KickPlayer(int clientId, bool ban)
+ {
+ if (!this.AmHost)
+ {
+ return;
+ }
+ MessageWriter messageWriter = MessageWriter.Get(SendOption.Reliable);
+ messageWriter.StartMessage(11);
+ messageWriter.Write(this.GameId);
+ messageWriter.WritePacked(clientId);
+ messageWriter.Write(ban);
+ messageWriter.EndMessage();
+ this.SendOrDisconnect(messageWriter);
+ messageWriter.Recycle();
+ }
+
+ public MessageWriter StartEndGame()
+ {
+ MessageWriter messageWriter = MessageWriter.Get(SendOption.Reliable);
+ messageWriter.StartMessage(8);
+ messageWriter.Write(this.GameId);
+ return messageWriter;
+ }
+
+ public void FinishEndGame(MessageWriter msg)
+ {
+ msg.EndMessage();
+ this.SendOrDisconnect(msg);
+ msg.Recycle();
+ }
+
+ protected void SendLateRejection(int targetId, DisconnectReasons reason)
+ {
+ MessageWriter messageWriter = MessageWriter.Get(SendOption.Reliable);
+ messageWriter.StartMessage(4);
+ messageWriter.Write(this.GameId);
+ messageWriter.WritePacked(targetId);
+ messageWriter.Write((byte)reason);
+ messageWriter.EndMessage();
+ this.SendOrDisconnect(messageWriter);
+ messageWriter.Recycle();
+ }
+
+ protected void SendClientReady()
+ {
+ if (!this.AmHost)
+ {
+ MessageWriter messageWriter = MessageWriter.Get(SendOption.Reliable);
+ messageWriter.StartMessage(5);
+ messageWriter.Write(this.GameId);
+ messageWriter.StartMessage(7);
+ messageWriter.WritePacked(this.ClientId);
+ messageWriter.EndMessage();
+ messageWriter.EndMessage();
+ this.SendOrDisconnect(messageWriter);
+ messageWriter.Recycle();
+ return;
+ }
+ ClientData clientData = this.FindClientById(this.ClientId);
+ if (clientData == null)
+ {
+ this.HandleDisconnect(DisconnectReasons.Error, "Couldn't find self as host");
+ return;
+ }
+ clientData.IsReady = true;
+ }
+
+ protected void SendStartGame()
+ {
+ MessageWriter messageWriter = MessageWriter.Get(SendOption.Reliable);
+ messageWriter.StartMessage(2);
+ messageWriter.Write(this.GameId);
+ messageWriter.EndMessage();
+ this.SendOrDisconnect(messageWriter);
+ messageWriter.Recycle();
+ }
+
+ public void RequestGameList(bool includePrivate, IBytesSerializable settings)
+ {
+ MessageWriter messageWriter = MessageWriter.Get(SendOption.Reliable);
+ messageWriter.StartMessage(9);
+ messageWriter.Write(includePrivate);
+ messageWriter.WriteBytesAndSize(settings.ToBytes());
+ messageWriter.EndMessage();
+ this.SendOrDisconnect(messageWriter);
+ messageWriter.Recycle();
+ }
+
+ public void ChangeGamePublic(bool isPublic)
+ {
+ if (this.AmHost)
+ {
+ MessageWriter messageWriter = MessageWriter.Get(SendOption.Reliable);
+ messageWriter.StartMessage(10);
+ messageWriter.Write(this.GameId);
+ messageWriter.Write(1);
+ messageWriter.Write(isPublic);
+ messageWriter.EndMessage();
+ this.SendOrDisconnect(messageWriter);
+ messageWriter.Recycle();
+ this.IsGamePublic = isPublic;
+ }
+ }
+
+ //c 收到数据,在网络线程
+ private void OnMessageReceived(DataReceivedEventArgs e)
+ {
+ MessageReader message = e.Message;
+ try
+ {
+ while (message.Position < message.Length)
+ {
+ this.HandleMessage(message.ReadMessage());
+ }
+ }
+ finally
+ {
+ message.Recycle();
+ }
+ }
+
+
+ //c 从imposter搞过来的
+ //c 后来发现Tags.cs里有
+ private static readonly Dictionary<byte, string> TagMap = new Dictionary<byte, string>
+ {
+ {0, "HostGame"},
+ {1, "JoinGame"},
+ {2, "StartGame"},
+ {3, "RemoveGame"},
+ {4, "RemovePlayer"},
+ {5, "GameData"},
+ {6, "GameDataTo"},
+ {7, "JoinedGame"},
+ {8, "EndGame"},
+ {9, "GetGameList"},
+ {10, "AlterGame"},
+ {11, "KickPlayer"},
+ {12, "WaitForHost"},
+ {13, "Redirect"},
+ {14, "ReselectServer"},
+ {16, "GetGameListV2"}
+ };
+
+
+ private enum TagAlias
+ {
+ HostGame = 0, // 创建
+ StartGame = 2, // 开始游戏
+ Disconnect = 3, // 断开
+ SubMessage = 6, //
+ JoinGame = 7, // 加入游戏
+ Gameover = 8, // 游戏结束
+ }
+
+ //c 处理收到的数据
+ private void HandleMessage(MessageReader reader)
+ {
+ List<Action> obj;
+ switch (reader.Tag)
+ {
+ case (int)TagAlias.HostGame:
+ this.GameId = reader.ReadInt32();
+ Debug.Log("Client hosting game: " + InnerNetClient.IntToGameName(this.GameId));
+ obj = this.Dispatcher;
+ lock (obj)
+ {
+ this.Dispatcher.Add(delegate
+ {
+ this.OnGameCreated(InnerNetClient.IntToGameName(this.GameId));
+ });
+ return;
+ }
+ break;
+ case 1:
+ goto IL_2F5;
+ case (int)TagAlias.StartGame:
+ this.GameState = InnerNetClient.GameStates.Started;
+ obj = this.Dispatcher;
+ lock (obj)
+ {
+ this.Dispatcher.Add(delegate
+ {
+ this.OnStartGame();
+ });
+ return;
+ }
+ goto IL_675;
+ case (int)TagAlias.Disconnect:
+ {
+ DisconnectReasons reason3 = DisconnectReasons.ServerRequest;
+ if (reader.Position < reader.Length)
+ {
+ reason3 = (DisconnectReasons)reader.ReadByte();
+ }
+ this.EnqueueDisconnect(reason3, null);
+ return;
+ }
+ case 4:
+ break;
+ case 5:
+ case (int)TagAlias.SubMessage: // 把这类消息存在队列里,主线程后续调用
+ {
+ int num = reader.ReadInt32();
+ if (this.GameId == num)
+ {
+ if (reader.Tag == 6)
+ {
+ int num2 = reader.ReadPackedInt32();
+ if (this.ClientId != num2)
+ {
+ Debug.LogWarning(string.Format("Got data meant for {0}", num2));
+ return;
+ }
+ }
+ MessageReader subReader;
+ if (this.InOnlineScene)
+ {
+ subReader = MessageReader.Get(reader);
+ obj = this.Dispatcher;
+ lock (obj)
+ {
+ this.Dispatcher.Add(delegate
+ {
+ this.HandleGameData(subReader, 0); // 在主线程调用
+ });
+ return;
+ }
+ }
+ Debug.Log("Stored early game data");
+ subReader = MessageReader.Get(reader);
+ obj = this.PreSpawnDispatcher;
+ lock (obj)
+ {
+ this.PreSpawnDispatcher.Add(delegate
+ {
+ this.HandleGameData(subReader, 0); // 在主线程调用
+ });
+ return;
+ }
+ goto IL_517;
+ }
+ return;
+ }
+ case (int)TagAlias.JoinGame:
+ goto IL_235;
+ case (int)TagAlias.Gameover:
+ {
+ int num3 = reader.ReadInt32();
+ if (this.GameId == num3 && this.GameState != InnerNetClient.GameStates.Ended)
+ {
+ this.GameState = InnerNetClient.GameStates.Ended;
+ List<ClientData> obj2 = this.allClients;
+ lock (obj2)
+ {
+ this.allClients.Clear();
+ }
+ GameOverReason reason = (GameOverReason)reader.ReadByte();
+ bool showAd = reader.ReadBoolean();
+ obj = this.Dispatcher;
+ lock (obj)
+ {
+ this.Dispatcher.Add(delegate
+ {
+ this.OnGameEnd(reason, showAd);
+ });
+ return;
+ }
+ goto IL_1DD;
+ }
+ return;
+ }
+ case 9:
+ goto IL_517;
+ case 10:
+ goto IL_5BC;
+ case 11:
+ goto IL_675;
+ case 12:
+ goto IL_1DD;
+ case 13:
+ {
+ uint address = reader.ReadUInt32();
+ ushort port = reader.ReadUInt16();
+ AmongUsClient.Instance.SetEndpoint(InnerNetClient.AddressToString(address), port);
+ obj = this.Dispatcher;
+ lock (obj)
+ {
+ this.Dispatcher.Add(delegate
+ {
+ Debug.Log(string.Format("Redirected to: {0}:{1}", this.networkAddress, this.networkPort));
+ base.StopAllCoroutines();
+ this.Connect(this.mode);
+ });
+ return;
+ }
+ goto IL_70A;
+ }
+ default:
+ goto IL_70A;
+ }
+ int num4 = reader.ReadInt32();
+ if (this.GameId == num4)
+ {
+ int playerIdThatLeft = reader.ReadInt32();
+ int hostId = reader.ReadInt32();
+ DisconnectReasons reason2 = (DisconnectReasons)reader.ReadByte();
+ if (!this.AmHost)
+ {
+ this.HostId = hostId;
+ if (this.AmHost)
+ {
+ obj = this.Dispatcher;
+ lock (obj)
+ {
+ this.Dispatcher.Add(delegate
+ {
+ this.OnBecomeHost();
+ });
+ }
+ }
+ }
+ this.RemovePlayer(playerIdThatLeft, reason2);
+ return;
+ }
+ return;
+ IL_1DD:
+ int num5 = reader.ReadInt32();
+ if (this.GameId != num5)
+ {
+ return;
+ }
+ this.ClientId = reader.ReadInt32();
+ obj = this.Dispatcher;
+ lock (obj)
+ {
+ this.Dispatcher.Add(delegate
+ {
+ this.OnWaitForHost(InnerNetClient.IntToGameName(this.GameId));
+ });
+ return;
+ }
+ IL_235:
+ int num6 = reader.ReadInt32();
+ if (this.GameId != num6 || this.GameState == InnerNetClient.GameStates.Joined)
+ {
+ return;
+ }
+ this.GameState = InnerNetClient.GameStates.Joined;
+ this.ClientId = reader.ReadInt32();
+ ClientData myClient = this.GetOrCreateClient(this.ClientId);
+ this.HostId = reader.ReadInt32();
+ int num7 = reader.ReadPackedInt32();
+ for (int i = 0; i < num7; i++)
+ {
+ this.GetOrCreateClient(reader.ReadPackedInt32());
+ }
+ obj = this.Dispatcher;
+ lock (obj)
+ {
+ this.Dispatcher.Add(delegate
+ {
+ this.OnGameJoined(InnerNetClient.IntToGameName(this.GameId), myClient);
+ });
+ return;
+ }
+ IL_2F5:
+ int num8 = reader.ReadInt32();
+ DisconnectReasons disconnectReasons = (DisconnectReasons)num8;
+ if (InnerNetClient.disconnectReasons.Contains(disconnectReasons))
+ {
+ if (disconnectReasons == DisconnectReasons.Custom)
+ {
+ this.LastCustomDisconnect = reader.ReadString();
+ }
+ this.GameId = -1;
+ this.EnqueueDisconnect(disconnectReasons, null);
+ return;
+ }
+ if (this.GameId == num8)
+ {
+ int num9 = reader.ReadInt32();
+ bool amHost = this.AmHost;
+ this.HostId = reader.ReadInt32();
+ ClientData client = this.GetOrCreateClient(num9);
+ Debug.Log(string.Format("Player {0} joined", num9));
+ obj = this.Dispatcher;
+ lock (obj)
+ {
+ this.Dispatcher.Add(delegate
+ {
+ this.OnPlayerJoined(client);
+ });
+ }
+ if (!this.AmHost || amHost)
+ {
+ return;
+ }
+ obj = this.Dispatcher;
+ lock (obj)
+ {
+ this.Dispatcher.Add(delegate
+ {
+ this.OnBecomeHost();
+ });
+ return;
+ }
+ }
+ this.EnqueueDisconnect(DisconnectReasons.IncorrectGame, null);
+ return;
+ IL_517:
+ int totalGames = reader.ReadPackedInt32();
+ List<GameListing> output = new List<GameListing>();
+ while (reader.Position < reader.Length)
+ {
+ output.Add(new GameListing(reader.ReadInt32(), reader.ReadByte(), reader.ReadByte(), reader.ReadByte(), reader.ReadPackedInt32(), reader.ReadString()));
+ }
+ obj = this.Dispatcher;
+ lock (obj)
+ {
+ this.Dispatcher.Add(delegate
+ {
+ this.OnGetGameList(totalGames, output);
+ });
+ return;
+ }
+ IL_5BC:
+ int num10 = reader.ReadInt32();
+ if (this.GameId != num10)
+ {
+ return;
+ }
+ byte b = reader.ReadByte();
+ if (b == 1)
+ {
+ this.IsGamePublic = reader.ReadBoolean();
+ string str = "Alter Public = ";
+ bool flag = this.IsGamePublic;
+ Debug.Log(str + flag.ToString());
+ return;
+ }
+ Debug.Log("Alter unknown");
+ return;
+ IL_675:
+ int num11 = reader.ReadInt32();
+ if (this.GameId == num11 && reader.ReadPackedInt32() == this.ClientId)
+ {
+ this.EnqueueDisconnect(reader.ReadBoolean() ? DisconnectReasons.Banned : DisconnectReasons.Kicked, null);
+ return;
+ }
+ return;
+ IL_70A:
+ Debug.Log(string.Format("Bad tag {0} at {1}+{2}={3}: ", new object[]
+ {
+ reader.Tag,
+ reader.Offset,
+ reader.Position,
+ reader.Length
+ }) + string.Join<byte>(" ", reader.Buffer));
+ }
+
+ private static string AddressToString(uint address)
+ {
+ return string.Format("{0}.{1}.{2}.{3}", new object[]
+ {
+ (byte)address,
+ (byte)(address >> 8),
+ (byte)(address >> 16),
+ (byte)(address >> 24)
+ });
+ }
+
+ private ClientData GetOrCreateClient(int clientId)
+ {
+ List<ClientData> obj = this.allClients;
+ ClientData clientData;
+ lock (obj)
+ {
+ clientData = this.allClients.FirstOrDefault((ClientData c) => c.Id == clientId);
+ if (clientData == null)
+ {
+ clientData = new ClientData(clientId);
+ this.allClients.Add(clientData);
+ }
+ }
+ return clientData;
+ }
+
+ private void RemovePlayer(int playerIdThatLeft, DisconnectReasons reason)
+ {
+ ClientData client = null;
+ List<ClientData> obj = this.allClients;
+ lock (obj)
+ {
+ for (int i = 0; i < this.allClients.Count; i++)
+ {
+ ClientData clientData = this.allClients[i];
+ if (clientData.Id == playerIdThatLeft)
+ {
+ client = clientData;
+ this.allClients.RemoveAt(i);
+ break;
+ }
+ }
+ }
+ if (client != null)
+ {
+ List<Action> dispatcher = this.Dispatcher;
+ lock (dispatcher)
+ {
+ this.Dispatcher.Add(delegate
+ {
+ this.OnPlayerLeft(client, reason);
+ });
+ }
+ }
+ }
+
+ protected virtual void OnApplicationPause(bool pause)
+ {
+ this.appPaused = pause;
+ if (!pause)
+ {
+ Debug.Log("Resumed Game");
+ if (this.AmHost)
+ {
+ this.RemoveUnownedObjects();
+ return;
+ }
+ }
+ else if (this.GameState != InnerNetClient.GameStates.Ended && this.AmConnected)
+ {
+ Debug.Log("Lost focus during game");
+ ThreadPool.QueueUserWorkItem(new WaitCallback(this.WaitToDisconnect));
+ }
+ }
+
+ private void WaitToDisconnect(object state)
+ {
+ int num = 0;
+ while (num < 10 && this.appPaused)
+ {
+ Thread.Sleep(1000);
+ num++;
+ }
+ if (this.appPaused && this.GameState != InnerNetClient.GameStates.Ended && this.AmConnected)
+ {
+ this.DisconnectInternal(DisconnectReasons.FocusLostBackground, null);
+ this.EnqueueDisconnect(DisconnectReasons.FocusLost, null);
+ }
+ }
+
+ protected void SendInitialData(int clientId)
+ {
+ MessageWriter messageWriter = MessageWriter.Get(SendOption.Reliable);
+ messageWriter.StartMessage(6);
+ messageWriter.Write(this.GameId);
+ messageWriter.WritePacked(clientId);
+ List<InnerNetObject> obj = this.allObjects;
+ lock (obj)
+ {
+ HashSet<GameObject> hashSet = new HashSet<GameObject>();
+ for (int i = 0; i < this.allObjects.Count; i++)
+ {
+ InnerNetObject innerNetObject = this.allObjects[i];
+ if (innerNetObject && hashSet.Add(innerNetObject.gameObject))
+ {
+ this.WriteSpawnMessage(innerNetObject, innerNetObject.OwnerId, innerNetObject.SpawnFlags, messageWriter);
+ }
+ }
+ }
+ messageWriter.EndMessage();
+ this.SendOrDisconnect(messageWriter);
+ messageWriter.Recycle();
+ }
+
+ protected abstract void OnGameCreated(string gameIdString);
+
+ protected abstract void OnGameJoined(string gameIdString, ClientData client);
+
+ protected abstract void OnWaitForHost(string gameIdString);
+
+ protected abstract void OnStartGame();
+
+ protected abstract void OnGameEnd(GameOverReason reason, bool showAd);
+
+ protected abstract void OnBecomeHost();
+
+ protected abstract void OnPlayerJoined(ClientData client);
+
+ protected abstract void OnPlayerChangedScene(ClientData client, string targetScene);
+
+ protected abstract void OnPlayerLeft(ClientData client, DisconnectReasons reason);
+
+ protected abstract void OnDisconnected();
+
+ protected abstract void OnGetGameList(int totalGames, List<GameListing> availableGames);
+
+ protected abstract byte[] GetConnectionData();
+
+ protected ClientData FindClientById(int id)
+ {
+ if (id < 0)
+ {
+ return null;
+ }
+ List<ClientData> obj = this.allClients;
+ ClientData result;
+ lock (obj)
+ {
+ for (int i = 0; i < this.allClients.Count; i++)
+ {
+ ClientData clientData = this.allClients[i];
+ if (clientData.Id == id)
+ {
+ return clientData;
+ }
+ }
+ result = null;
+ }
+ return result;
+ }
+
+ public static string IntToGameName(int gameId)
+ {
+ char[] array = new char[]
+ {
+ (char)(gameId & 255),
+ (char)(gameId >> 8 & 255),
+ (char)(gameId >> 16 & 255),
+ (char)(gameId >> 24 & 255)
+ };
+ if (array.Any((char c) => c < 'A' || c > 'z'))
+ {
+ return null;
+ }
+ return new string(array);
+ }
+
+ public static int GameNameToInt(string gameId)
+ {
+ if (gameId.Length != 4)
+ {
+ return -1;
+ }
+ gameId = gameId.ToUpperInvariant();
+ return (int)(gameId[0] | (int)gameId[1] << 8 | (int)gameId[2] << 16 | (int)gameId[3] << 24);
+ }
+
+ private void FixedUpdate()
+ {
+ if (this.mode == MatchMakerModes.None || this.Streams == null)
+ {
+ this.timer = 0f;
+ return;
+ }
+ this.timer += Time.fixedDeltaTime;
+ if (this.timer < this.MinSendInterval)
+ {
+ return;
+ }
+ this.timer = 0f;
+
+ //c 写入所有场景内包含InnerNetObject派生类的数据
+ List<InnerNetObject> obj = this.allObjects;
+ lock (obj)
+ {
+ for (int i = 0; i < this.allObjects.Count; i++)
+ {
+ InnerNetObject innerNetObject = this.allObjects[i];
+ if (innerNetObject && innerNetObject.DirtyBits != 0U && (innerNetObject.AmOwner || (innerNetObject.OwnerId == -2 && this.AmHost)))
+ {
+ MessageWriter messageWriter = this.Streams[(int)innerNetObject.sendMode];
+ messageWriter.StartMessage(1);
+ messageWriter.WritePacked(innerNetObject.NetId);
+ if (innerNetObject.Serialize(messageWriter, false))
+ {
+ messageWriter.EndMessage();
+ }
+ else
+ {
+ messageWriter.CancelMessage();
+ }
+ }
+ }
+ }
+
+ for (int j = 0; j < this.Streams.Length; j++)
+ {
+ MessageWriter messageWriter2 = this.Streams[j];
+ if (messageWriter2.HasBytes(7))
+ {
+ messageWriter2.EndMessage();
+ this.SendOrDisconnect(messageWriter2);
+ messageWriter2.Clear((SendOption)j);
+ messageWriter2.StartMessage(5);
+ messageWriter2.Write(this.GameId);
+ }
+ }
+ }
+
+ public T FindObjectByNetId<T>(uint netId) where T : InnerNetObject
+ {
+ InnerNetObject innerNetObject;
+ if (this.allObjectsFast.TryGetValue(netId, out innerNetObject))
+ {
+ return (T)((object)innerNetObject);
+ }
+ return default(T);
+ }
+
+ public void SendRpcImmediately(uint targetNetId, byte callId, SendOption option)
+ {
+ MessageWriter messageWriter = MessageWriter.Get(option);
+ messageWriter.StartMessage(5);
+ messageWriter.Write(this.GameId);
+ messageWriter.StartMessage(2);
+ messageWriter.WritePacked(targetNetId);
+ messageWriter.Write(callId);
+ messageWriter.EndMessage();
+ messageWriter.EndMessage();
+ this.connection.Send(messageWriter);
+ messageWriter.Recycle();
+ }
+
+ public MessageWriter StartRpcImmediately(uint targetNetId, byte callId, SendOption option, int targetClientId = -1)
+ {
+ MessageWriter messageWriter = MessageWriter.Get(option);
+ if (targetClientId < 0)
+ {
+ messageWriter.StartMessage(5);
+ messageWriter.Write(this.GameId);
+ }
+ else
+ {
+ messageWriter.StartMessage(6);
+ messageWriter.Write(this.GameId);
+ messageWriter.WritePacked(targetClientId);
+ }
+ messageWriter.StartMessage(2);
+ messageWriter.WritePacked(targetNetId);
+ messageWriter.Write(callId);
+ return messageWriter;
+ }
+
+ public void FinishRpcImmediately(MessageWriter msg)
+ {
+ msg.EndMessage();
+ msg.EndMessage();
+ this.SendOrDisconnect(msg);
+ msg.Recycle();
+ }
+
+ public void SendRpc(uint targetNetId, byte callId, SendOption option = SendOption.Reliable)
+ {
+ this.StartRpc(targetNetId, callId, option).EndMessage();
+ }
+
+ public MessageWriter StartRpc(uint targetNetId, byte callId, SendOption option = SendOption.Reliable)
+ {
+ MessageWriter messageWriter = this.Streams[(int)option];
+ messageWriter.StartMessage(2);
+ messageWriter.WritePacked(targetNetId);
+ messageWriter.Write(callId);
+ return messageWriter;
+ }
+
+ private void SendSceneChange(string sceneName)
+ {
+ this.InOnlineScene = string.Equals(sceneName, "OnlineGame");
+ if (!this.AmConnected)
+ {
+ return;
+ }
+ Debug.Log("Changed To " + sceneName);
+ base.StartCoroutine(this.CoSendSceneChange(sceneName));
+ }
+
+ private IEnumerator CoSendSceneChange(string sceneName)
+ {
+ List<InnerNetObject> obj = this.allObjects;
+ lock (obj)
+ {
+ for (int i = this.allObjects.Count - 1; i > -1; i--)
+ {
+ if (!this.allObjects[i])
+ {
+ this.allObjects.RemoveAt(i);
+ }
+ }
+ goto IL_BF;
+ }
+ IL_A8:
+ yield return null;
+ IL_BF:
+ if (this.AmConnected && this.ClientId < 0)
+ {
+ goto IL_A8;
+ }
+ if (!this.AmConnected)
+ {
+ yield break;
+ }
+ if (!this.AmHost && this.connection.State == ConnectionState.Connected)
+ {
+ MessageWriter messageWriter = MessageWriter.Get(SendOption.Reliable);
+ messageWriter.StartMessage(5);
+ messageWriter.Write(this.GameId);
+ messageWriter.StartMessage(6);
+ messageWriter.WritePacked(this.ClientId);
+ messageWriter.Write(sceneName);
+ messageWriter.EndMessage();
+ messageWriter.EndMessage();
+ this.SendOrDisconnect(messageWriter);
+ messageWriter.Recycle();
+ }
+ ClientData client = this.FindClientById(this.ClientId);
+ if (client != null)
+ {
+ Debug.Log(string.Format("Self changed scene: {0} {1}", this.ClientId, sceneName));
+ List<Action> dispatcher = this.Dispatcher;
+ lock (dispatcher)
+ {
+ this.Dispatcher.Add(delegate
+ {
+ this.OnPlayerChangedScene(client, sceneName);
+ });
+ yield break;
+ }
+ }
+ Debug.Log(string.Format("Couldn't find self in clients: {0}: ", this.ClientId) + sceneName);
+ yield break;
+ }
+
+ public void Spawn(InnerNetObject netObjParent, int ownerId = -2, SpawnFlags flags = SpawnFlags.None)
+ {
+ if (this.AmHost)
+ {
+ ownerId = ((ownerId == -3) ? this.ClientId : ownerId);
+ MessageWriter msg = this.Streams[1];
+ this.WriteSpawnMessage(netObjParent, ownerId, flags, msg);
+ return;
+ }
+ if (!this.AmClient)
+ {
+ return;
+ }
+ Debug.LogError("Tried to spawn while not host:" + netObjParent);
+ }
+
+ private void WriteSpawnMessage(InnerNetObject netObjParent, int ownerId, SpawnFlags flags, MessageWriter msg)
+ {
+ msg.StartMessage(4);
+ msg.WritePacked(netObjParent.SpawnId);
+ msg.WritePacked(ownerId);
+ msg.Write((byte)flags);
+ InnerNetObject[] componentsInChildren = netObjParent.GetComponentsInChildren<InnerNetObject>();
+ msg.WritePacked(componentsInChildren.Length);
+ foreach (InnerNetObject innerNetObject in componentsInChildren)
+ {
+ innerNetObject.OwnerId = ownerId;
+ innerNetObject.SpawnFlags = flags;
+ if (innerNetObject.NetId == 0U)
+ {
+ InnerNetObject innerNetObject2 = innerNetObject;
+ uint netIdCnt = this.NetIdCnt;
+ this.NetIdCnt = netIdCnt + 1U;
+ innerNetObject2.NetId = netIdCnt;
+ this.allObjects.Add(innerNetObject);
+ this.allObjectsFast.Add(innerNetObject.NetId, innerNetObject);
+ }
+ msg.WritePacked(innerNetObject.NetId);
+ msg.StartMessage(1);
+ innerNetObject.Serialize(msg, true);
+ msg.EndMessage();
+ }
+ msg.EndMessage();
+ }
+
+ public void Despawn(InnerNetObject objToDespawn)
+ {
+ if (objToDespawn.NetId < 1U)
+ {
+ Debug.LogError("Tried to net destroy: " + objToDespawn);
+ return;
+ }
+ MessageWriter messageWriter = this.Streams[1];
+ messageWriter.StartMessage(5);
+ messageWriter.WritePacked(objToDespawn.NetId);
+ messageWriter.EndMessage();
+ this.RemoveNetObject(objToDespawn);
+ }
+
+ private bool AddNetObject(InnerNetObject obj)
+ {
+ uint num = obj.NetId + 1U;
+ if (num > this.NetIdCnt)
+ {
+ this.NetIdCnt = num;
+ }
+ if (!this.allObjectsFast.ContainsKey(obj.NetId))
+ {
+ this.allObjects.Add(obj);
+ this.allObjectsFast.Add(obj.NetId, obj);
+ return true;
+ }
+ return false;
+ }
+
+ public void RemoveNetObject(InnerNetObject obj)
+ {
+ int num = this.allObjects.IndexOf(obj);
+ if (num > -1)
+ {
+ this.allObjects.RemoveAt(num);
+ }
+ this.allObjectsFast.Remove(obj.NetId);
+ obj.NetId = uint.MaxValue;
+ }
+
+ public void RemoveUnownedObjects()
+ {
+ HashSet<int> hashSet = new HashSet<int>();
+ hashSet.Add(-2);
+ List<ClientData> obj = this.allClients;
+ lock (obj)
+ {
+ for (int i = 0; i < this.allClients.Count; i++)
+ {
+ ClientData clientData = this.allClients[i];
+ if (clientData.Character)
+ {
+ hashSet.Add(clientData.Id);
+ }
+ }
+ }
+ List<InnerNetObject> obj2 = this.allObjects;
+ lock (obj2)
+ {
+ for (int j = this.allObjects.Count - 1; j > -1; j--)
+ {
+ InnerNetObject innerNetObject = this.allObjects[j];
+ if (!innerNetObject)
+ {
+ this.allObjects.RemoveAt(j);
+ }
+ else if (!hashSet.Contains(innerNetObject.OwnerId))
+ {
+ innerNetObject.OwnerId = this.ClientId;
+ UnityEngine.Object.Destroy(innerNetObject.gameObject);
+ }
+ }
+ }
+ }
+
+ private void HandleGameData(MessageReader parentReader, int cnt = 0)
+ {
+ try
+ {
+ while (parentReader.Position < parentReader.Length)
+ {
+ this.HandleGameDataInner(parentReader.ReadMessage(), cnt);
+ }
+ }
+ finally
+ {
+ parentReader.Recycle();
+ }
+ }
+
+ //c 辅助tag别名
+ private enum SubTagAlias
+ {
+ Normal = 1, // 游戏内的简单数据,比如同步角色位置、动画等
+ Rpc = 2, // 远程调用Remote Procedure Call
+ SpawnCharacter = 4, // 生成角色
+ RemoveNetObjectByNetId = 5, // 删除数据
+ ChangeScene = 6, // 切换场景
+ PlayerReady = 7, // 角色准备好了
+ }
+
+ //c 处理收到的数据,用来同步
+ //c 这个方法是在主线程调用的
+ private void HandleGameDataInner(MessageReader reader, int cnt)
+ {
+ switch (reader.Tag)
+ {
+ case (int)SubTagAlias.Normal:
+ {
+ uint num = reader.ReadPackedUInt32();
+ InnerNetObject innerNetObject;
+ if (this.allObjectsFast.TryGetValue(num, out innerNetObject))
+ {
+ innerNetObject.Deserialize(reader, false);
+ return;
+ }
+ if (!this.DestroyedObjects.Contains(num))
+ {
+ this.DeferMessage(cnt, reader, "Stored data for " + num);
+ return;
+ }
+ return;
+ }
+ case (int)SubTagAlias.Rpc:
+ {
+ // 根据编号找到对应的同步数据
+ uint index = reader.ReadPackedUInt32();
+ InnerNetObject innerNetObject2;
+ if (this.allObjectsFast.TryGetValue(index, out innerNetObject2))
+ {
+ byte callId = reader.ReadByte();
+ innerNetObject2.HandleRpc(callId, reader);
+ return;
+ }
+ if (!this.DestroyedObjects.Contains(index))
+ {
+ this.DeferMessage(cnt, reader, "Stored RPC for " + index);
+ return;
+ }
+ return;
+ }
+ case (int)SubTagAlias.SpawnCharacter:
+ {
+ uint num3 = reader.ReadPackedUInt32();
+ if ((ulong)num3 >= (ulong)((long)this.SpawnableObjects.Length))
+ {
+ Debug.LogError("Couldn't find spawnable prefab: " + num3);
+ return;
+ }
+ int num4 = reader.ReadPackedInt32();
+ ClientData clientData = this.FindClientById(num4);
+ if (num4 > 0 && clientData == null)
+ {
+ this.DeferMessage(cnt, reader, "Delay spawn for unowned " + num3);
+ return;
+ }
+ // 创建角色对象并设置参数
+ InnerNetObject innerNetObject3 = UnityEngine.Object.Instantiate<InnerNetObject>(this.SpawnableObjects[(int)num3]);
+ innerNetObject3.SpawnFlags = (SpawnFlags)reader.ReadByte();
+ if ((innerNetObject3.SpawnFlags & SpawnFlags.IsClientCharacter) != SpawnFlags.None)
+ {
+ if (!clientData.Character)
+ {
+ clientData.InScene = true;
+ clientData.Character = (innerNetObject3 as PlayerControl);
+ }
+ else if (innerNetObject3)
+ {
+ Debug.LogWarning(string.Format("Double spawn character: {0} already has {1}", clientData.Id, clientData.Character.NetId));
+ UnityEngine.Object.Destroy(innerNetObject3.gameObject);
+ return;
+ }
+ }
+ int num5 = reader.ReadPackedInt32();
+ InnerNetObject[] componentsInChildren = innerNetObject3.GetComponentsInChildren<InnerNetObject>();
+ if (num5 != componentsInChildren.Length)
+ {
+ Debug.LogError("Children didn't match for spawnable " + num3);
+ UnityEngine.Object.Destroy(innerNetObject3.gameObject);
+ return;
+ }
+ for (int i = 0; i < num5; i++)
+ {
+ InnerNetObject innerNetObject4 = componentsInChildren[i];
+ innerNetObject4.NetId = reader.ReadPackedUInt32();
+ innerNetObject4.OwnerId = num4;
+ if (this.DestroyedObjects.Contains(innerNetObject4.NetId))
+ {
+ innerNetObject3.NetId = uint.MaxValue;
+ UnityEngine.Object.Destroy(innerNetObject3.gameObject);
+ return;
+ }
+ if (!this.AddNetObject(innerNetObject4))
+ {
+ innerNetObject3.NetId = uint.MaxValue;
+ UnityEngine.Object.Destroy(innerNetObject3.gameObject);
+ return;
+ }
+ MessageReader messageReader = reader.ReadMessage();
+ if (messageReader.Length > 0)
+ {
+ innerNetObject4.Deserialize(messageReader, true);
+ }
+ }
+ return;
+ }
+ case (int)SubTagAlias.RemoveNetObjectByNetId:
+ {
+ uint netId = reader.ReadPackedUInt32();
+ this.DestroyedObjects.Add(netId);
+ InnerNetObject innerNetObject5 = this.FindObjectByNetId<InnerNetObject>(netId);
+ if (innerNetObject5)
+ {
+ this.RemoveNetObject(innerNetObject5);
+ UnityEngine.Object.Destroy(innerNetObject5.gameObject);
+ return;
+ }
+ return;
+ }
+ case (int)SubTagAlias.ChangeScene:
+ {
+ int id = reader.ReadPackedInt32();
+ ClientData client = this.FindClientById(id); // 找到对应的玩家
+ string targetScene = reader.ReadString();
+ if (client != null && !string.IsNullOrWhiteSpace(targetScene))
+ {
+ Debug.Log(string.Format("Client {0} changed scene to {1}", client.Id, targetScene));
+ List<Action> dispatcher = this.Dispatcher;
+ lock (dispatcher)
+ {
+ this.Dispatcher.Add(delegate
+ {
+ // 切换场景
+ this.OnPlayerChangedScene(client, targetScene);
+ });
+ return;
+ }
+ }
+ Debug.Log(string.Format("Couldn't find client {0} to change scene to {1}", id, targetScene));
+ return;
+ }
+ case (int)SubTagAlias.PlayerReady:
+ {
+ ClientData clientData2 = this.FindClientById(reader.ReadPackedInt32());
+ if (clientData2 != null)
+ {
+ Debug.Log(string.Format("Client {0} ready", clientData2.Id));
+ clientData2.IsReady = true;
+ return;
+ }
+ return;
+ }
+ }
+
+ Debug.Log(string.Format("Bad tag {0} at {1}+{2}={3}: ", new object[]
+ {
+ reader.Tag,
+ reader.Offset,
+ reader.Position,
+ reader.Length
+ }) + string.Join<byte>(" ", reader.Buffer));
+ }
+
+ private void DeferMessage(int cnt, MessageReader reader, string logMsg)
+ {
+ if (cnt > 10)
+ {
+ Debug.Log("Giving up on: " + logMsg);
+ return;
+ }
+ int cnt2 = cnt;
+ cnt = cnt2 + 1;
+ Debug.Log(logMsg);
+ MessageReader copy = MessageReader.CopyMessageIntoParent(reader);
+ List<Action> preSpawnDispatcher = this.PreSpawnDispatcher;
+ lock (preSpawnDispatcher)
+ {
+ this.PreSpawnDispatcher.Add(delegate
+ {
+ this.HandleGameData(copy, cnt);
+ });
+ }
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/InnerNet/InnerNetObject.cs b/Client/Assembly-CSharp/InnerNet/InnerNetObject.cs
new file mode 100644
index 0000000..0fdcf2d
--- /dev/null
+++ b/Client/Assembly-CSharp/InnerNet/InnerNetObject.cs
@@ -0,0 +1,74 @@
+using System;
+using Hazel;
+using UnityEngine;
+
+namespace InnerNet
+{
+ public abstract class InnerNetObject : MonoBehaviour, IComparable<InnerNetObject>
+ {
+ public bool AmOwner
+ {
+ get
+ {
+ return this.OwnerId == AmongUsClient.Instance.ClientId;
+ }
+ }
+
+ public uint SpawnId;
+
+ public uint NetId;
+
+ public uint DirtyBits;
+
+ public SpawnFlags SpawnFlags;
+
+ public SendOption sendMode = SendOption.Reliable;
+
+ public int OwnerId;
+
+ protected bool DespawnOnDestroy = true;
+
+ public void Despawn()
+ {
+ UnityEngine.Object.Destroy(base.gameObject);
+ AmongUsClient.Instance.Despawn(this);
+ }
+
+ public virtual void OnDestroy()
+ {
+ if (AmongUsClient.Instance && this.NetId != 4294967295U)
+ {
+ if (this.DespawnOnDestroy && this.AmOwner)
+ {
+ AmongUsClient.Instance.Despawn(this);
+ return;
+ }
+ AmongUsClient.Instance.RemoveNetObject(this);
+ }
+ }
+
+ public abstract void HandleRpc(byte callId, MessageReader reader);
+
+ public abstract bool Serialize(MessageWriter writer, bool initialState);
+
+ public abstract void Deserialize(MessageReader reader, bool initialState);
+
+ public int CompareTo(InnerNetObject other)
+ {
+ if (this.NetId > other.NetId)
+ {
+ return 1;
+ }
+ if (this.NetId < other.NetId)
+ {
+ return -1;
+ }
+ return 0;
+ }
+
+ protected void SetDirtyBit(uint val)
+ {
+ this.DirtyBits |= val;
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/InnerNet/InnerNetServer.cs b/Client/Assembly-CSharp/InnerNet/InnerNetServer.cs
new file mode 100644
index 0000000..3705318
--- /dev/null
+++ b/Client/Assembly-CSharp/InnerNet/InnerNetServer.cs
@@ -0,0 +1,592 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Threading;
+using Hazel;
+using Hazel.Udp;
+using UnityEngine;
+
+namespace InnerNet
+{
+ public class InnerNetServer : DestroyableSingleton<InnerNetServer>
+ {
+ public const int MaxPlayers = 10;
+
+ public bool Running;
+
+ public const int LocalGameId = 32;
+
+ private const int InvalidHost = -1;
+
+ private int HostId = -1;
+
+ public HashSet<string> ipBans = new HashSet<string>();
+
+ public int Port = 22023;
+
+ [SerializeField]
+ private GameStates GameState;
+
+ private NetworkConnectionListener listener;
+
+ private List<InnerNetServer.Player> Clients = new List<InnerNetServer.Player>();
+
+ protected class Player
+ {
+ private static int IdCount = 1;
+
+ public int Id;
+
+ public Connection Connection;
+
+ public LimboStates LimboState;
+
+ public Player(Connection connection)
+ {
+ this.Id = Interlocked.Increment(ref InnerNetServer.Player.IdCount);
+ this.Connection = connection;
+ }
+ }
+
+ public override void OnDestroy()
+ {
+ this.StopServer();
+ base.OnDestroy();
+ }
+
+ public void StartAsServer()
+ {
+ if (this.listener != null)
+ {
+ this.StopServer();
+ }
+ this.GameState = GameStates.NotStarted;
+ this.listener = new UdpConnectionListener(new IPEndPoint(IPAddress.Any, this.Port), IPMode.IPv4, null);
+ this.listener.NewConnection += this.OnServerConnect;
+ this.listener.Start();
+ this.Running = true;
+ }
+
+ public void StopServer()
+ {
+ this.HostId = -1;
+ this.Running = false;
+ this.GameState = GameStates.Destroyed;
+ if (this.listener != null)
+ {
+ this.listener.Close();
+ this.listener.Dispose();
+ this.listener = null;
+ }
+ List<InnerNetServer.Player> clients = this.Clients;
+ lock (clients)
+ {
+ this.Clients.Clear();
+ }
+ }
+
+ public static bool IsCompatibleVersion(int version)
+ {
+ return Constants.CompatVersions.Contains(version);
+ }
+
+ private void OnServerConnect(NewConnectionEventArgs evt)
+ {
+ MessageReader handshakeData = evt.HandshakeData;
+ try
+ {
+ if (evt.HandshakeData.Length < 5)
+ {
+ InnerNetServer.SendIncorrectVersion(evt.Connection);
+ return;
+ }
+ if (!InnerNetServer.IsCompatibleVersion(handshakeData.ReadInt32()))
+ {
+ InnerNetServer.SendIncorrectVersion(evt.Connection);
+ return;
+ }
+ }
+ finally
+ {
+ handshakeData.Recycle();
+ }
+ InnerNetServer.Player client = new InnerNetServer.Player(evt.Connection);
+ Debug.Log(string.Format("Client {0} added: {1}", client.Id, evt.Connection.EndPoint));
+ UdpConnection udpConnection = (UdpConnection)evt.Connection;
+ udpConnection.KeepAliveInterval = 1500;
+ udpConnection.DisconnectTimeout = 6000;
+ udpConnection.ResendPingMultiplier = 1.5f;
+ udpConnection.DataReceived += delegate(DataReceivedEventArgs e)
+ {
+ this.OnDataReceived(client, e);
+ };
+ udpConnection.Disconnected += delegate(object o, DisconnectedEventArgs e)
+ {
+ this.ClientDisconnect(client);
+ };
+ }
+
+ private static void SendIncorrectVersion(Connection connection)
+ {
+ MessageWriter messageWriter = MessageWriter.Get(SendOption.Reliable);
+ messageWriter.StartMessage(1);
+ messageWriter.Write(5);
+ messageWriter.EndMessage();
+ connection.Send(messageWriter);
+ messageWriter.Recycle();
+ }
+
+ private void Connection_DataSentRaw(byte[] data, int length)
+ {
+ Debug.Log("Server Sent: " + string.Join(" ", (from b in data
+ select b.ToString()).ToArray<string>(), 0, length));
+ }
+
+ private void OnDataReceived(InnerNetServer.Player client, DataReceivedEventArgs evt)
+ {
+ MessageReader message = evt.Message;
+ if (message.Length <= 0)
+ {
+ Debug.Log("Server got 0 bytes");
+ message.Recycle();
+ return;
+ }
+ try
+ {
+ while (message.Position < message.Length)
+ {
+ this.HandleMessage(client, message.ReadMessage(), evt.SendOption);
+ }
+ }
+ catch (Exception arg)
+ {
+ Debug.Log(string.Format("{0}\r\n{1}", string.Join<byte>(" ", message.Buffer), arg));
+ }
+ finally
+ {
+ message.Recycle();
+ }
+ }
+
+ private void HandleMessage(InnerNetServer.Player client, MessageReader reader, SendOption sendOption)
+ {
+ switch (reader.Tag)
+ {
+ case 0:
+ {
+ Debug.Log("Server got host game");
+ MessageWriter messageWriter = MessageWriter.Get(SendOption.Reliable);
+ messageWriter.StartMessage(0);
+ messageWriter.Write(32);
+ messageWriter.EndMessage();
+ client.Connection.Send(messageWriter);
+ messageWriter.Recycle();
+ return;
+ }
+ case 1:
+ {
+ Debug.Log("Server got join game");
+ if (reader.ReadInt32() == 32)
+ {
+ this.JoinGame(client);
+ return;
+ }
+ MessageWriter messageWriter2 = MessageWriter.Get(SendOption.Reliable);
+ messageWriter2.StartMessage(1);
+ messageWriter2.Write(3);
+ messageWriter2.EndMessage();
+ client.Connection.Send(messageWriter2);
+ messageWriter2.Recycle();
+ return;
+ }
+ case 2:
+ if (reader.ReadInt32() == 32)
+ {
+ this.StartGame(reader, client);
+ return;
+ }
+ break;
+ case 3:
+ if (reader.ReadInt32() == 32)
+ {
+ this.ClientDisconnect(client);
+ return;
+ }
+ break;
+ case 4:
+ case 7:
+ case 9:
+ case 10:
+ break;
+ case 5:
+ if (this.Clients.Contains(client))
+ {
+ if (reader.ReadInt32() == 32)
+ {
+ MessageWriter messageWriter3 = MessageWriter.Get(sendOption);
+ messageWriter3.CopyFrom(reader);
+ this.Broadcast(messageWriter3, client);
+ messageWriter3.Recycle();
+ return;
+ }
+ }
+ else if (this.GameState == GameStates.Started)
+ {
+ client.Connection.Dispose();
+ return;
+ }
+ break;
+ case 6:
+ if (this.Clients.Contains(client))
+ {
+ if (reader.ReadInt32() == 32)
+ {
+ int targetId = reader.ReadPackedInt32();
+ MessageWriter messageWriter4 = MessageWriter.Get(sendOption);
+ messageWriter4.CopyFrom(reader);
+ this.SendTo(messageWriter4, targetId);
+ messageWriter4.Recycle();
+ return;
+ }
+ }
+ else if (this.GameState == GameStates.Started)
+ {
+ Debug.Log("GameDataTo: Server didn't have client");
+ client.Connection.Dispose();
+ return;
+ }
+ break;
+ case 8:
+ if (reader.ReadInt32() == 32)
+ {
+ this.EndGame(reader, client);
+ return;
+ }
+ break;
+ case 11:
+ if (reader.ReadInt32() == 32)
+ {
+ this.KickPlayer(reader.ReadPackedInt32(), reader.ReadBoolean());
+ }
+ break;
+ default:
+ return;
+ }
+ }
+
+ private void KickPlayer(int targetId, bool ban)
+ {
+ List<InnerNetServer.Player> clients = this.Clients;
+ lock (clients)
+ {
+ InnerNetServer.Player player = null;
+ for (int i = 0; i < this.Clients.Count; i++)
+ {
+ if (this.Clients[i].Id == targetId)
+ {
+ player = this.Clients[i];
+ break;
+ }
+ }
+ if (player != null)
+ {
+ if (ban)
+ {
+ HashSet<string> obj = this.ipBans;
+ lock (obj)
+ {
+ IPEndPoint endPoint = player.Connection.EndPoint;
+ this.ipBans.Add(endPoint.Address.ToString());
+ }
+ }
+ MessageWriter messageWriter = MessageWriter.Get(SendOption.Reliable);
+ messageWriter.StartMessage(11);
+ messageWriter.Write(32);
+ messageWriter.WritePacked(targetId);
+ messageWriter.Write(ban);
+ messageWriter.EndMessage();
+ this.Broadcast(messageWriter, null);
+ messageWriter.Recycle();
+ }
+ }
+ }
+
+ protected void JoinGame(InnerNetServer.Player client)
+ {
+ HashSet<string> obj = this.ipBans;
+ lock (obj)
+ {
+ IPEndPoint endPoint = client.Connection.EndPoint;
+ if (this.ipBans.Contains(endPoint.Address.ToString()))
+ {
+ MessageWriter messageWriter = MessageWriter.Get(SendOption.Reliable);
+ messageWriter.StartMessage(1);
+ messageWriter.Write(6);
+ messageWriter.EndMessage();
+ client.Connection.Send(messageWriter);
+ messageWriter.Recycle();
+ return;
+ }
+ }
+ List<InnerNetServer.Player> clients = this.Clients;
+ lock (clients)
+ {
+ switch (this.GameState)
+ {
+ case GameStates.NotStarted:
+ this.HandleNewGameJoin(client);
+ break;
+ default:
+ {
+ MessageWriter messageWriter2 = MessageWriter.Get(SendOption.Reliable);
+ messageWriter2.StartMessage(1);
+ messageWriter2.Write(2);
+ messageWriter2.EndMessage();
+ client.Connection.Send(messageWriter2);
+ messageWriter2.Recycle();
+ break;
+ }
+ case GameStates.Ended:
+ this.HandleRejoin(client);
+ break;
+ }
+ }
+ }
+
+ private void HandleRejoin(InnerNetServer.Player client)
+ {
+ if (client.Id == this.HostId)
+ {
+ this.GameState = GameStates.NotStarted;
+ this.HandleNewGameJoin(client);
+ MessageWriter messageWriter = MessageWriter.Get(SendOption.Reliable);
+ for (int i = 0; i < this.Clients.Count; i++)
+ {
+ InnerNetServer.Player player = this.Clients[i];
+ if (player != client)
+ {
+ try
+ {
+ this.WriteJoinedMessage(player, messageWriter, true);
+ player.Connection.Send(messageWriter);
+ }
+ catch
+ {
+ }
+ }
+ }
+ messageWriter.Recycle();
+ return;
+ }
+ if (this.Clients.Count >= 9)
+ {
+ MessageWriter messageWriter2 = MessageWriter.Get(SendOption.Reliable);
+ messageWriter2.StartMessage(1);
+ messageWriter2.Write(1);
+ messageWriter2.EndMessage();
+ client.Connection.Send(messageWriter2);
+ messageWriter2.Recycle();
+ return;
+ }
+ this.Clients.Add(client);
+ client.LimboState = LimboStates.WaitingForHost;
+ MessageWriter messageWriter3 = MessageWriter.Get(SendOption.Reliable);
+ try
+ {
+ messageWriter3.StartMessage(12);
+ messageWriter3.Write(32);
+ messageWriter3.Write(client.Id);
+ messageWriter3.EndMessage();
+ client.Connection.Send(messageWriter3);
+ this.BroadcastJoinMessage(client, messageWriter3);
+ }
+ catch
+ {
+ }
+ finally
+ {
+ messageWriter3.Recycle();
+ }
+ }
+
+ private void HandleNewGameJoin(InnerNetServer.Player client)
+ {
+ if (this.Clients.Count >= 10)
+ {
+ MessageWriter messageWriter = MessageWriter.Get(SendOption.Reliable);
+ try
+ {
+ messageWriter.StartMessage(1);
+ messageWriter.Write(1);
+ messageWriter.EndMessage();
+ client.Connection.Send(messageWriter);
+ }
+ catch
+ {
+ }
+ finally
+ {
+ messageWriter.Recycle();
+ }
+ return;
+ }
+ this.Clients.Add(client);
+ client.LimboState = LimboStates.PreSpawn;
+ if (this.HostId == -1)
+ {
+ this.HostId = this.Clients[0].Id;
+ }
+ if (this.HostId == client.Id)
+ {
+ client.LimboState = LimboStates.NotLimbo;
+ }
+ MessageWriter messageWriter2 = MessageWriter.Get(SendOption.Reliable);
+ try
+ {
+ this.WriteJoinedMessage(client, messageWriter2, true);
+ client.Connection.Send(messageWriter2);
+ this.BroadcastJoinMessage(client, messageWriter2);
+ }
+ catch
+ {
+ }
+ finally
+ {
+ messageWriter2.Recycle();
+ }
+ }
+
+ private void EndGame(MessageReader message, InnerNetServer.Player source)
+ {
+ if (source.Id == this.HostId)
+ {
+ this.GameState = GameStates.Ended;
+ MessageWriter messageWriter = MessageWriter.Get(SendOption.Reliable);
+ messageWriter.CopyFrom(message);
+ this.Broadcast(messageWriter, null);
+ messageWriter.Recycle();
+ List<InnerNetServer.Player> clients = this.Clients;
+ lock (clients)
+ {
+ this.Clients.Clear();
+ return;
+ }
+ }
+ Debug.LogWarning("Reset request rejected from: " + source.Id);
+ }
+
+ private void StartGame(MessageReader message, InnerNetServer.Player source)
+ {
+ this.GameState = GameStates.Started;
+ MessageWriter messageWriter = MessageWriter.Get(SendOption.Reliable);
+ messageWriter.CopyFrom(message);
+ this.Broadcast(messageWriter, null);
+ messageWriter.Recycle();
+ }
+
+ private void ClientDisconnect(InnerNetServer.Player client)
+ {
+ Debug.Log("Server DC client " + client.Id);
+ List<InnerNetServer.Player> clients = this.Clients;
+ lock (clients)
+ {
+ this.Clients.Remove(client);
+ client.Connection.Dispose();
+ if (this.Clients.Count > 0)
+ {
+ this.HostId = this.Clients[0].Id;
+ }
+ }
+ MessageWriter messageWriter = MessageWriter.Get(SendOption.Reliable);
+ messageWriter.StartMessage(4);
+ messageWriter.Write(32);
+ messageWriter.Write(client.Id);
+ messageWriter.Write(this.HostId);
+ messageWriter.Write(0);
+ messageWriter.EndMessage();
+ this.Broadcast(messageWriter, null);
+ messageWriter.Recycle();
+ }
+
+ protected void SendTo(MessageWriter msg, int targetId)
+ {
+ List<InnerNetServer.Player> clients = this.Clients;
+ lock (clients)
+ {
+ for (int i = 0; i < this.Clients.Count; i++)
+ {
+ InnerNetServer.Player player = this.Clients[i];
+ if (player.Id == targetId)
+ {
+ try
+ {
+ player.Connection.Send(msg);
+ break;
+ }
+ catch (Exception exception)
+ {
+ Debug.LogException(exception);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ protected void Broadcast(MessageWriter msg, InnerNetServer.Player source)
+ {
+ List<InnerNetServer.Player> clients = this.Clients;
+ lock (clients)
+ {
+ for (int i = 0; i < this.Clients.Count; i++)
+ {
+ InnerNetServer.Player player = this.Clients[i];
+ if (player != source)
+ {
+ try
+ {
+ player.Connection.Send(msg);
+ }
+ catch
+ {
+ }
+ }
+ }
+ }
+ }
+
+ private void BroadcastJoinMessage(InnerNetServer.Player client, MessageWriter msg)
+ {
+ msg.Clear(SendOption.Reliable);
+ msg.StartMessage(1);
+ msg.Write(32);
+ msg.Write(client.Id);
+ msg.Write(this.HostId);
+ msg.EndMessage();
+ this.Broadcast(msg, client);
+ }
+
+ private void WriteJoinedMessage(InnerNetServer.Player client, MessageWriter msg, bool clear)
+ {
+ if (clear)
+ {
+ msg.Clear(SendOption.Reliable);
+ }
+ msg.StartMessage(7);
+ msg.Write(32);
+ msg.Write(client.Id);
+ msg.Write(this.HostId);
+ msg.WritePacked(this.Clients.Count - 1);
+ for (int i = 0; i < this.Clients.Count; i++)
+ {
+ InnerNetServer.Player player = this.Clients[i];
+ if (player != client)
+ {
+ msg.WritePacked(player.Id);
+ }
+ }
+ msg.EndMessage();
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/InnerNet/JoinFailureReasons.cs b/Client/Assembly-CSharp/InnerNet/JoinFailureReasons.cs
new file mode 100644
index 0000000..6e5bf37
--- /dev/null
+++ b/Client/Assembly-CSharp/InnerNet/JoinFailureReasons.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace InnerNet
+{
+ public enum JoinFailureReasons : byte
+ {
+ TooManyPlayers = 1,
+ GameStarted,
+ GameNotFound,
+ HostNotReady,
+ IncorrectVersion,
+ Banned,
+ Kicked
+ }
+}
diff --git a/Client/Assembly-CSharp/InnerNet/LimboStates.cs b/Client/Assembly-CSharp/InnerNet/LimboStates.cs
new file mode 100644
index 0000000..80446bb
--- /dev/null
+++ b/Client/Assembly-CSharp/InnerNet/LimboStates.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace InnerNet
+{
+ public enum LimboStates
+ {
+ PreSpawn,
+ NotLimbo,
+ WaitingForHost
+ }
+}
diff --git a/Client/Assembly-CSharp/InnerNet/MatchMakerModes.cs b/Client/Assembly-CSharp/InnerNet/MatchMakerModes.cs
new file mode 100644
index 0000000..64604a4
--- /dev/null
+++ b/Client/Assembly-CSharp/InnerNet/MatchMakerModes.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace InnerNet
+{
+ public enum MatchMakerModes
+ {
+ None,
+ Client,
+ HostAndClient
+ }
+}
diff --git a/Client/Assembly-CSharp/InnerNet/MessageExtensions.cs b/Client/Assembly-CSharp/InnerNet/MessageExtensions.cs
new file mode 100644
index 0000000..9e9bd49
--- /dev/null
+++ b/Client/Assembly-CSharp/InnerNet/MessageExtensions.cs
@@ -0,0 +1,24 @@
+using System;
+using Hazel;
+
+namespace InnerNet
+{
+ public static class MessageExtensions
+ {
+ public static void WriteNetObject(this MessageWriter self, InnerNetObject obj)
+ {
+ if (!obj)
+ {
+ self.Write(0);
+ return;
+ }
+ self.WritePacked(obj.NetId);
+ }
+
+ public static T ReadNetObject<T>(this MessageReader self) where T : InnerNetObject
+ {
+ uint netId = self.ReadPackedUInt32();
+ return AmongUsClient.Instance.FindObjectByNetId<T>(netId);
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/InnerNet/SpawnFlags.cs b/Client/Assembly-CSharp/InnerNet/SpawnFlags.cs
new file mode 100644
index 0000000..644e4e9
--- /dev/null
+++ b/Client/Assembly-CSharp/InnerNet/SpawnFlags.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace InnerNet
+{
+ [Flags]
+ public enum SpawnFlags : byte
+ {
+ None = 0,
+ IsClientCharacter = 1
+ }
+}
diff --git a/Client/Assembly-CSharp/InnerNet/Tags.cs b/Client/Assembly-CSharp/InnerNet/Tags.cs
new file mode 100644
index 0000000..aa48fc3
--- /dev/null
+++ b/Client/Assembly-CSharp/InnerNet/Tags.cs
@@ -0,0 +1,35 @@
+using System;
+
+namespace InnerNet
+{
+ public static class Tags
+ {
+ public const byte HostGame = 0;
+
+ public const byte JoinGame = 1;
+
+ public const byte StartGame = 2;
+
+ public const byte RemoveGame = 3;
+
+ public const byte RemovePlayer = 4;
+
+ public const byte GameData = 5;
+
+ public const byte GameDataTo = 6;
+
+ public const byte JoinedGame = 7;
+
+ public const byte EndGame = 8;
+
+ public const byte GetGameList = 9;
+
+ public const byte AlterGame = 10;
+
+ public const byte KickPlayer = 11;
+
+ public const byte WaitForHost = 12;
+
+ public const byte Redirect = 13;
+ }
+}
diff --git a/Client/Assembly-CSharp/IntRange.cs b/Client/Assembly-CSharp/IntRange.cs
new file mode 100644
index 0000000..1989b3b
--- /dev/null
+++ b/Client/Assembly-CSharp/IntRange.cs
@@ -0,0 +1,71 @@
+using System;
+using UnityEngine;
+
+[Serializable]
+public class IntRange
+{
+ public int min;
+
+ public int max;
+
+ public IntRange()
+ {
+ }
+
+ public IntRange(int min, int max)
+ {
+ this.min = min;
+ this.max = max;
+ }
+
+ public int Next()
+ {
+ return UnityEngine.Random.Range(this.min, this.max);
+ }
+
+ public bool Contains(int value)
+ {
+ return this.min <= value && this.max >= value;
+ }
+
+ public static int Next(int max)
+ {
+ return (int)(UnityEngine.Random.value * (float)max);
+ }
+
+ internal static int Next(int min, int max)
+ {
+ return UnityEngine.Random.Range(min, max);
+ }
+
+ internal static byte NextByte(byte max)
+ {
+ return (byte)UnityEngine.Random.Range(0, (int)max);
+ }
+
+ public static void FillRandom(sbyte min, sbyte max, sbyte[] array)
+ {
+ for (int i = 0; i < array.Length; i++)
+ {
+ array[i] = (sbyte)IntRange.Next((int)min, (int)max);
+ }
+ }
+
+ public static int RandomSign()
+ {
+ if (!BoolRange.Next(0.5f))
+ {
+ return -1;
+ }
+ return 1;
+ }
+
+ public static void FillRandomRange(sbyte[] array)
+ {
+ for (int i = 0; i < array.Length; i++)
+ {
+ array[i] = (sbyte)i;
+ }
+ array.Shuffle<sbyte>();
+ }
+}
diff --git a/Client/Assembly-CSharp/IntroCutscene.cs b/Client/Assembly-CSharp/IntroCutscene.cs
new file mode 100644
index 0000000..3271c11
--- /dev/null
+++ b/Client/Assembly-CSharp/IntroCutscene.cs
@@ -0,0 +1,155 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class IntroCutscene : MonoBehaviour
+{
+ public static IntroCutscene Instance;
+
+ public TextRenderer Title;
+
+ public TextRenderer ImpostorText;
+
+ public PoolablePlayer PlayerPrefab;
+
+ public MeshRenderer BackgroundBar;
+
+ public MeshRenderer Foreground;
+
+ public FloatRange ForegroundRadius;
+
+ public SpriteRenderer FrontMost;
+
+ public AudioClip IntroStinger;
+
+ public float BaseY = -0.25f;
+
+ public IEnumerator CoBegin(List<PlayerControl> yourTeam, bool isImpostor)
+ {
+ SoundManager.Instance.PlaySound(this.IntroStinger, false, 1f);
+ if (!isImpostor)
+ {
+ this.BeginCrewmate(yourTeam);
+ }
+ else
+ {
+ this.BeginImpostor(yourTeam);
+ }
+ Color c = this.Title.Color;
+ Color fade = Color.black;
+ Color impColor = Color.white;
+ Vector3 titlePos = this.Title.transform.localPosition;
+ float timer = 0f;
+ while (timer < 3f)
+ {
+ timer += Time.deltaTime;
+ float num = Mathf.Min(1f, timer / 3f);
+ this.Foreground.material.SetFloat("_Rad", this.ForegroundRadius.ExpOutLerp(num * 2f));
+ fade.a = Mathf.Lerp(1f, 0f, num * 3f);
+ this.FrontMost.color = fade;
+ c.a = Mathf.Clamp(FloatRange.ExpOutLerp(num, 0f, 1f), 0f, 1f);
+ this.Title.Color = c;
+ impColor.a = Mathf.Lerp(0f, 1f, (num - 0.3f) * 3f);
+ this.ImpostorText.Color = impColor;
+ titlePos.y = 2.7f - num * 0.3f;
+ this.Title.transform.localPosition = titlePos;
+ yield return null;
+ }
+ timer = 0f;
+ while (timer < 1f)
+ {
+ timer += Time.deltaTime;
+ float num2 = timer / 1f;
+ fade.a = Mathf.Lerp(0f, 1f, num2 * 3f);
+ this.FrontMost.color = fade;
+ yield return null;
+ }
+ UnityEngine.Object.Destroy(base.gameObject);
+ yield break;
+ }
+
+ private void BeginCrewmate(List<PlayerControl> yourTeam)
+ {
+ Vector3 position = this.BackgroundBar.transform.position;
+ position.y -= 0.25f;
+ this.BackgroundBar.transform.position = position;
+ int adjustedNumImpostors = PlayerControl.GameOptions.GetAdjustedNumImpostors(GameData.Instance.PlayerCount);
+ if (adjustedNumImpostors == 1)
+ {
+ this.ImpostorText.Text = DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.NumImpostorsS, Array.Empty<object>());
+ }
+ else
+ {
+ this.ImpostorText.Text = DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.NumImpostorsP, new object[]
+ {
+ adjustedNumImpostors
+ });
+ }
+ this.BackgroundBar.material.SetColor("_Color", Palette.CrewmateBlue);
+ this.Title.Text = DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.Crewmate, Array.Empty<object>());
+ this.Title.Color = Palette.CrewmateBlue;
+ for (int i = 0; i < yourTeam.Count; i++)
+ {
+ PlayerControl playerControl = yourTeam[i];
+ if (playerControl)
+ {
+ GameData.PlayerInfo data = playerControl.Data;
+ if (data != null)
+ {
+ int num = (i % 2 == 0) ? -1 : 1;
+ int num2 = (i + 1) / 2;
+ float num3 = ((i == 0) ? 1.2f : 1f) - (float)num2 * 0.12f;
+ float num4 = 1f - (float)num2 * 0.08f;
+ float num5 = (float)((i == 0) ? -8 : -1);
+ PoolablePlayer poolablePlayer = UnityEngine.Object.Instantiate<PoolablePlayer>(this.PlayerPrefab, base.transform);
+ poolablePlayer.name = data.PlayerName + "Dummy";
+ poolablePlayer.SetFlipX(i % 2 == 0);
+ poolablePlayer.transform.localPosition = new Vector3(0.8f * (float)num * (float)num2 * num4, this.BaseY - 0.25f + (float)num2 * 0.1f, num5 + (float)num2 * 0.01f) * 1.5f;
+ Vector3 localScale = new Vector3(num3, num3, num3) * 1.5f;
+ poolablePlayer.transform.localScale = localScale;
+ PlayerControl.SetPlayerMaterialColors((int)data.ColorId, poolablePlayer.Body);
+ DestroyableSingleton<HatManager>.Instance.SetSkin(poolablePlayer.SkinSlot, data.SkinId);
+ PlayerControl.SetHatImage(data.HatId, poolablePlayer.HatSlot);
+ PlayerControl.SetPetImage(data.PetId, (int)data.ColorId, poolablePlayer.PetSlot);
+ poolablePlayer.NameText.gameObject.SetActive(false);
+ }
+ }
+ }
+ }
+
+ private void BeginImpostor(List<PlayerControl> yourTeam)
+ {
+ this.ImpostorText.gameObject.SetActive(false);
+ this.Title.Text = DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.Impostor, Array.Empty<object>());
+ this.Title.Color = Palette.ImpostorRed;
+ for (int i = 0; i < yourTeam.Count; i++)
+ {
+ PlayerControl playerControl = yourTeam[i];
+ if (playerControl)
+ {
+ GameData.PlayerInfo data = playerControl.Data;
+ if (data != null)
+ {
+ int num = (i % 2 == 0) ? -1 : 1;
+ int num2 = (i + 1) / 2;
+ float num3 = 1f - (float)num2 * 0.075f;
+ float num4 = 1f - (float)num2 * 0.035f;
+ float num5 = (float)((i == 0) ? -8 : -1);
+ PoolablePlayer poolablePlayer = UnityEngine.Object.Instantiate<PoolablePlayer>(this.PlayerPrefab, base.transform);
+ poolablePlayer.transform.localPosition = new Vector3((float)(num * num2) * num4, this.BaseY + (float)num2 * 0.15f, num5 + (float)num2 * 0.01f) * 1.5f;
+ Vector3 vector = new Vector3(num3, num3, num3) * 1.5f;
+ poolablePlayer.transform.localScale = vector;
+ poolablePlayer.SetFlipX(i % 2 == 1);
+ PlayerControl.SetPlayerMaterialColors((int)data.ColorId, poolablePlayer.Body);
+ DestroyableSingleton<HatManager>.Instance.SetSkin(poolablePlayer.SkinSlot, data.SkinId);
+ PlayerControl.SetHatImage(data.HatId, poolablePlayer.HatSlot);
+ PlayerControl.SetPetImage(data.PetId, (int)data.ColorId, poolablePlayer.PetSlot);
+ TextRenderer nameText = poolablePlayer.NameText;
+ nameText.Text = data.PlayerName;
+ nameText.transform.localScale = vector.Inv();
+ }
+ }
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/JoinGameButton.cs b/Client/Assembly-CSharp/JoinGameButton.cs
new file mode 100644
index 0000000..f9cea88
--- /dev/null
+++ b/Client/Assembly-CSharp/JoinGameButton.cs
@@ -0,0 +1,119 @@
+using System;
+using System.Collections;
+using InnerNet;
+using PowerTools;
+using UnityEngine;
+
+public class JoinGameButton : MonoBehaviour, IConnectButton
+{
+ public AudioClip IntroMusic;
+
+ public TextBox GameIdText;
+
+ public TextRenderer gameNameText;
+
+ public float timeRecieved;
+
+ public SpriteRenderer FillScreen;
+
+ public SpriteAnim connectIcon;
+
+ public AnimationClip connectClip;
+
+ public GameModes GameMode;
+
+ public string netAddress;
+
+ public void OnClick()
+ {
+ if (string.IsNullOrWhiteSpace(this.netAddress))
+ {
+ return;
+ }
+ if (NameTextBehaviour.Instance.ShakeIfInvalid())
+ {
+ return;
+ }
+ if (StatsManager.Instance.AmBanned)
+ {
+ AmongUsClient.Instance.LastDisconnectReason = DisconnectReasons.IntentionalLeaving;
+ DestroyableSingleton<DisconnectPopup>.Instance.Show();
+ return;
+ }
+ if (!DestroyableSingleton<MatchMaker>.Instance.Connecting(this))
+ {
+ return;
+ }
+ AmongUsClient.Instance.GameMode = this.GameMode;
+ if (this.GameMode == GameModes.OnlineGame)
+ {
+ AmongUsClient.Instance.SetEndpoint(DestroyableSingleton<ServerManager>.Instance.OnlineNetAddress, 22023);
+ AmongUsClient.Instance.MainMenuScene = "MMOnline";
+ int num = InnerNetClient.GameNameToInt(this.GameIdText.text);
+ if (num == -1)
+ {
+ base.StartCoroutine(Effects.Shake(this.GameIdText.transform, 0.75f, 0.25f));
+ DestroyableSingleton<MatchMaker>.Instance.NotConnecting();
+ return;
+ }
+ AmongUsClient.Instance.GameId = num;
+ }
+ else
+ {
+ AmongUsClient.Instance.SetEndpoint(this.netAddress, 22023);
+ AmongUsClient.Instance.GameId = 32;
+ AmongUsClient.Instance.GameMode = GameModes.LocalGame;
+ AmongUsClient.Instance.MainMenuScene = "MatchMaking";
+ }
+ base.StartCoroutine(this.JoinGame());
+ }
+
+ private IEnumerator JoinGame()
+ {
+ if (this.FillScreen)
+ {
+ SoundManager.Instance.CrossFadeSound("MainBG", null, 0.5f, 1.5f);
+ this.FillScreen.gameObject.SetActive(true);
+ for (float time = 0f; time < 0.25f; time += Time.deltaTime)
+ {
+ this.FillScreen.color = Color.Lerp(Color.clear, Color.black, time / 0.25f);
+ yield return null;
+ }
+ this.FillScreen.color = Color.black;
+ }
+ AmongUsClient.Instance.OnlineScene = "OnlineGame";
+ AmongUsClient.Instance.Connect(MatchMakerModes.Client);
+ yield return AmongUsClient.Instance.WaitForConnectionOrFail();
+ if (AmongUsClient.Instance.mode == MatchMakerModes.None)
+ {
+ if (this.FillScreen)
+ {
+ SoundManager.Instance.CrossFadeSound("MainBG", this.IntroMusic, 0.5f, 1.5f);
+ for (float time = 0f; time < 0.25f; time += Time.deltaTime)
+ {
+ this.FillScreen.color = Color.Lerp(Color.black, Color.clear, time / 0.25f);
+ yield return null;
+ }
+ this.FillScreen.color = Color.clear;
+ }
+ DestroyableSingleton<MatchMaker>.Instance.NotConnecting();
+ }
+ yield break;
+ }
+
+ public void SetGameName(string[] gameNameParts)
+ {
+ this.gameNameText.Text = gameNameParts[0] + " (" + gameNameParts[2] + "/10)";
+ }
+
+ public void StartIcon()
+ {
+ this.connectIcon.Play(this.connectClip, 1f);
+ }
+
+ public void StopIcon()
+ {
+ this.connectIcon.Stop();
+ this.connectIcon.GetComponent<SpriteRenderer>().sprite = null;
+ }
+}
diff --git a/Client/Assembly-CSharp/KerningPair.cs b/Client/Assembly-CSharp/KerningPair.cs
new file mode 100644
index 0000000..a264649
--- /dev/null
+++ b/Client/Assembly-CSharp/KerningPair.cs
@@ -0,0 +1,11 @@
+using System;
+
+[Serializable]
+public class KerningPair
+{
+ public char First;
+
+ public char Second;
+
+ public int Pixels = 4;
+}
diff --git a/Client/Assembly-CSharp/KeyboardJoystick.cs b/Client/Assembly-CSharp/KeyboardJoystick.cs
new file mode 100644
index 0000000..848eff3
--- /dev/null
+++ b/Client/Assembly-CSharp/KeyboardJoystick.cs
@@ -0,0 +1,79 @@
+using System;
+using UnityEngine;
+
+public class KeyboardJoystick : MonoBehaviour, IVirtualJoystick
+{
+ public Vector2 Delta
+ {
+ get
+ {
+ return this.del;
+ }
+ }
+
+ private Vector2 del;
+
+ private void Update()
+ {
+ if (!PlayerControl.LocalPlayer)
+ {
+ return;
+ }
+ this.del.x = (this.del.y = 0f);
+ if (Input.GetKey(KeyCode.RightArrow) || Input.GetKey(KeyCode.D))
+ {
+ this.del.x = this.del.x + 1f;
+ }
+ if (Input.GetKey(KeyCode.LeftArrow) || Input.GetKey(KeyCode.A))
+ {
+ this.del.x = this.del.x - 1f;
+ }
+ if (Input.GetKey(KeyCode.UpArrow) || Input.GetKey(KeyCode.W))
+ {
+ this.del.y = this.del.y + 1f;
+ }
+ if (Input.GetKey(KeyCode.DownArrow) || Input.GetKey(KeyCode.S))
+ {
+ this.del.y = this.del.y - 1f;
+ }
+ if (Input.GetKeyDown(KeyCode.R))
+ {
+ DestroyableSingleton<HudManager>.Instance.ReportButton.DoClick();
+ }
+ if (Input.GetKeyDown(KeyCode.Space) || Input.GetKeyDown(KeyCode.E))
+ {
+ DestroyableSingleton<HudManager>.Instance.UseButton.DoClick();
+ }
+ if (Input.GetKeyDown(KeyCode.Tab))
+ {
+ DestroyableSingleton<HudManager>.Instance.ShowMap(delegate(MapBehaviour m)
+ {
+ m.ShowNormalMap();
+ });
+ }
+ if (PlayerControl.LocalPlayer.Data.IsImpostor && Input.GetKeyDown(KeyCode.Q))
+ {
+ DestroyableSingleton<HudManager>.Instance.KillButton.PerformKill();
+ }
+ if (Input.GetKeyDown(KeyCode.Escape))
+ {
+ if (Minigame.Instance)
+ {
+ Minigame.Instance.Close();
+ }
+ else if (DestroyableSingleton<HudManager>.InstanceExists && MapBehaviour.Instance && MapBehaviour.Instance.IsOpen)
+ {
+ MapBehaviour.Instance.Close();
+ }
+ else
+ {
+ CustomPlayerMenu customPlayerMenu = UnityEngine.Object.FindObjectOfType<CustomPlayerMenu>();
+ if (customPlayerMenu)
+ {
+ customPlayerMenu.Close(true);
+ }
+ }
+ }
+ this.del.Normalize();
+ }
+}
diff --git a/Client/Assembly-CSharp/KeypadGame.cs b/Client/Assembly-CSharp/KeypadGame.cs
new file mode 100644
index 0000000..91d7a7a
--- /dev/null
+++ b/Client/Assembly-CSharp/KeypadGame.cs
@@ -0,0 +1,135 @@
+using System;
+using System.Collections;
+using UnityEngine;
+
+public class KeypadGame : Minigame
+{
+ public TextRenderer TargetText;
+
+ public TextRenderer NumberText;
+
+ public int number;
+
+ public string numString = string.Empty;
+
+ private bool animating;
+
+ public SpriteRenderer AcceptButton;
+
+ private LifeSuppSystemType system;
+
+ private NoOxyTask oxyTask;
+
+ private bool done;
+
+ public override void Begin(PlayerTask task)
+ {
+ base.Begin(task);
+ this.oxyTask = (NoOxyTask)task;
+ this.TargetText.Text = "today's code:\r\n" + this.oxyTask.targetNumber.ToString("D5");
+ this.NumberText.Text = string.Empty;
+ this.system = (LifeSuppSystemType)ShipStatus.Instance.Systems[SystemTypes.LifeSupp];
+ this.done = this.system.GetConsoleComplete(base.ConsoleId);
+ }
+
+ public void ClickNumber(int i)
+ {
+ if (this.animating)
+ {
+ return;
+ }
+ if (this.done)
+ {
+ return;
+ }
+ if (this.NumberText.Text.Length >= 5)
+ {
+ base.StartCoroutine(this.BlinkAccept());
+ return;
+ }
+ this.numString += i;
+ this.number = this.number * 10 + i;
+ this.NumberText.Text = this.numString;
+ }
+
+ private IEnumerator BlinkAccept()
+ {
+ int num;
+ for (int i = 0; i < 5; i = num)
+ {
+ this.AcceptButton.color = Color.gray;
+ yield return null;
+ yield return null;
+ this.AcceptButton.color = Color.white;
+ yield return null;
+ yield return null;
+ num = i + 1;
+ }
+ yield break;
+ }
+
+ public void ClearEntry()
+ {
+ if (this.animating)
+ {
+ return;
+ }
+ this.number = 0;
+ this.numString = string.Empty;
+ this.NumberText.Text = string.Empty;
+ }
+
+ public void Enter()
+ {
+ if (this.animating)
+ {
+ return;
+ }
+ base.StartCoroutine(this.Animate());
+ }
+
+ private IEnumerator Animate()
+ {
+ this.animating = true;
+ WaitForSeconds wait = new WaitForSeconds(0.1f);
+ yield return wait;
+ this.NumberText.Text = string.Empty;
+ yield return wait;
+ if (this.oxyTask.targetNumber == this.number)
+ {
+ this.done = true;
+ byte amount = (byte)(base.ConsoleId | 64);
+ ShipStatus.Instance.RpcRepairSystem(SystemTypes.LifeSupp, (int)amount);
+ try
+ {
+ ((SabotageTask)this.MyTask).MarkContributed();
+ }
+ catch
+ {
+ }
+ this.NumberText.Text = "OK";
+ yield return wait;
+ this.NumberText.Text = string.Empty;
+ yield return wait;
+ this.NumberText.Text = "OK";
+ yield return wait;
+ this.NumberText.Text = string.Empty;
+ yield return wait;
+ this.NumberText.Text = "OK";
+ }
+ else
+ {
+ this.NumberText.Text = "Bad";
+ yield return wait;
+ this.NumberText.Text = string.Empty;
+ yield return wait;
+ this.NumberText.Text = "Bad";
+ yield return wait;
+ this.numString = string.Empty;
+ this.number = 0;
+ this.NumberText.Text = this.numString;
+ }
+ this.animating = false;
+ yield break;
+ }
+}
diff --git a/Client/Assembly-CSharp/KillAnimType.cs b/Client/Assembly-CSharp/KillAnimType.cs
new file mode 100644
index 0000000..29b5198
--- /dev/null
+++ b/Client/Assembly-CSharp/KillAnimType.cs
@@ -0,0 +1,10 @@
+using System;
+
+public enum KillAnimType
+{
+ Stab,
+ Tongue,
+ Shoot,
+ Neck,
+ None
+}
diff --git a/Client/Assembly-CSharp/KillAnimation.cs b/Client/Assembly-CSharp/KillAnimation.cs
new file mode 100644
index 0000000..d6e980a
--- /dev/null
+++ b/Client/Assembly-CSharp/KillAnimation.cs
@@ -0,0 +1,52 @@
+using System;
+using System.Collections;
+using PowerTools;
+using UnityEngine;
+
+public class KillAnimation : MonoBehaviour
+{
+ public AnimationClip BlurAnim;
+
+ public DeadBody bodyPrefab;
+
+ public Vector3 BodyOffset;
+
+ public IEnumerator CoPerformKill(PlayerControl source, PlayerControl target)
+ {
+ bool isParticipant = PlayerControl.LocalPlayer == source || PlayerControl.LocalPlayer == target;
+ PlayerPhysics sourcePhys = source.MyPhysics;
+ KillAnimation.SetMovement(source, false);
+ KillAnimation.SetMovement(target, false);
+ if (isParticipant)
+ {
+ Camera.main.GetComponent<FollowerCamera>().Locked = true;
+ }
+ target.Die(DeathReason.Kill);
+ SpriteAnim sourceAnim = source.GetComponent<SpriteAnim>();
+ yield return new WaitForAnimationFinish(sourceAnim, this.BlurAnim);
+ source.NetTransform.SnapTo(target.transform.position);
+ sourceAnim.Play(sourcePhys.IdleAnim, 1f);
+ KillAnimation.SetMovement(source, true);
+ DeadBody deadBody = UnityEngine.Object.Instantiate<DeadBody>(this.bodyPrefab);
+ Vector3 vector = target.transform.position + this.BodyOffset;
+ vector.z = vector.y / 1000f;
+ deadBody.transform.position = vector;
+ deadBody.ParentId = target.PlayerId;
+ target.SetPlayerMaterialColors(deadBody.GetComponent<Renderer>());
+ KillAnimation.SetMovement(target, true);
+ if (isParticipant)
+ {
+ Camera.main.GetComponent<FollowerCamera>().Locked = false;
+ }
+ yield break;
+ }
+
+ public static void SetMovement(PlayerControl source, bool canMove)
+ {
+ source.moveable = canMove;
+ source.MyPhysics.ResetAnim(false);
+ source.NetTransform.enabled = canMove;
+ source.MyPhysics.enabled = canMove;
+ source.NetTransform.Halt();
+ }
+}
diff --git a/Client/Assembly-CSharp/KillButtonManager.cs b/Client/Assembly-CSharp/KillButtonManager.cs
new file mode 100644
index 0000000..6c43b4f
--- /dev/null
+++ b/Client/Assembly-CSharp/KillButtonManager.cs
@@ -0,0 +1,69 @@
+using System;
+using UnityEngine;
+
+public class KillButtonManager : MonoBehaviour
+{
+ public PlayerControl CurrentTarget;
+
+ public SpriteRenderer renderer;
+
+ public TextRenderer TimerText;
+
+ public bool isCoolingDown = true;
+
+ public bool isActive;
+
+ private Vector2 uv;
+
+ public void Start()
+ {
+ this.renderer.SetCooldownNormalizedUvs();
+ this.SetTarget(null);
+ }
+
+ public void PerformKill()
+ {
+ if (base.isActiveAndEnabled && this.CurrentTarget && !this.isCoolingDown && !PlayerControl.LocalPlayer.Data.IsDead && PlayerControl.LocalPlayer.CanMove)
+ {
+ PlayerControl.LocalPlayer.RpcMurderPlayer(this.CurrentTarget);
+ this.SetTarget(null);
+ }
+ }
+
+ public void SetTarget(PlayerControl target)
+ {
+ if (this.CurrentTarget && this.CurrentTarget != target)
+ {
+ this.CurrentTarget.GetComponent<SpriteRenderer>().material.SetFloat("_Outline", 0f);
+ }
+ this.CurrentTarget = target;
+ if (this.CurrentTarget)
+ {
+ SpriteRenderer component = this.CurrentTarget.GetComponent<SpriteRenderer>();
+ component.material.SetFloat("_Outline", (float)(this.isActive ? 1 : 0));
+ component.material.SetColor("_OutlineColor", Color.red);
+ this.renderer.color = Palette.EnabledColor;
+ this.renderer.material.SetFloat("_Desat", 0f);
+ return;
+ }
+ this.renderer.color = Palette.DisabledColor;
+ this.renderer.material.SetFloat("_Desat", 1f);
+ }
+
+ public void SetCoolDown(float timer, float maxTimer)
+ {
+ float num = Mathf.Clamp(timer / maxTimer, 0f, 1f);
+ if (this.renderer)
+ {
+ this.renderer.material.SetFloat("_Percent", num);
+ }
+ this.isCoolingDown = (num > 0f);
+ if (this.isCoolingDown)
+ {
+ this.TimerText.Text = Mathf.CeilToInt(timer).ToString();
+ this.TimerText.gameObject.SetActive(true);
+ return;
+ }
+ this.TimerText.gameObject.SetActive(false);
+ }
+}
diff --git a/Client/Assembly-CSharp/KillOverlay.cs b/Client/Assembly-CSharp/KillOverlay.cs
new file mode 100644
index 0000000..9c0c226
--- /dev/null
+++ b/Client/Assembly-CSharp/KillOverlay.cs
@@ -0,0 +1,114 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class KillOverlay : MonoBehaviour
+{
+ public bool IsOpen
+ {
+ get
+ {
+ return this.showAll != null || this.queue.Count > 0;
+ }
+ }
+
+ public SpriteRenderer background;
+
+ public GameObject flameParent;
+
+ public OverlayKillAnimation[] KillAnims;
+
+ public float FadeTime = 0.6f;
+
+ public OverlayKillAnimation EmergencyOverlay;
+
+ public OverlayKillAnimation ReportOverlay;
+
+ private Queue<Func<IEnumerator>> queue = new Queue<Func<IEnumerator>>();
+
+ private Coroutine showAll;
+
+ private Coroutine showOne;
+
+ public IEnumerator WaitForFinish()
+ {
+ while (this.showAll != null || this.queue.Count > 0)
+ {
+ yield return null;
+ }
+ yield break;
+ }
+
+ public void ShowOne(PlayerControl killer, GameData.PlayerInfo victim)
+ {
+ this.queue.Enqueue(() => this.CoShowOne(this.KillAnims.Random<OverlayKillAnimation>(), killer, victim));
+ if (this.showAll == null)
+ {
+ this.showAll = base.StartCoroutine(this.ShowAll());
+ }
+ }
+
+ public void ShowOne(OverlayKillAnimation killAnimPrefab, PlayerControl killer, GameData.PlayerInfo victim)
+ {
+ this.queue.Enqueue(() => this.CoShowOne(killAnimPrefab, killer, victim));
+ if (this.showAll == null)
+ {
+ this.showAll = base.StartCoroutine(this.ShowAll());
+ }
+ }
+
+ private IEnumerator ShowAll()
+ {
+ while (this.queue.Count > 0 || this.showOne != null)
+ {
+ if (this.showOne == null)
+ {
+ this.showOne = base.StartCoroutine(this.queue.Dequeue()());
+ }
+ yield return null;
+ }
+ this.showAll = null;
+ yield break;
+ }
+
+ private IEnumerator CoShowOne(OverlayKillAnimation killAnimPrefab, PlayerControl killer, GameData.PlayerInfo victim)
+ {
+ OverlayKillAnimation overlayKillAnimation = UnityEngine.Object.Instantiate<OverlayKillAnimation>(killAnimPrefab, base.transform);
+ overlayKillAnimation.Begin(killer, victim);
+ overlayKillAnimation.gameObject.SetActive(false);
+ yield return this.CoShowOne(overlayKillAnimation);
+ yield break;
+ }
+
+ private IEnumerator CoShowOne(OverlayKillAnimation anim)
+ {
+ if (Constants.ShouldPlaySfx())
+ {
+ SoundManager.Instance.PlaySound(anim.Stinger, false, 1f).volume = anim.StingerVolume;
+ }
+ WaitForSeconds wait = new WaitForSeconds(0.083333336f);
+ this.background.enabled = true;
+ yield return wait;
+ this.background.enabled = false;
+ this.flameParent.SetActive(true);
+ this.flameParent.transform.localScale = new Vector3(1f, 0.3f, 1f);
+ this.flameParent.transform.localEulerAngles = new Vector3(0f, 0f, 25f);
+ yield return wait;
+ this.flameParent.transform.localScale = new Vector3(1f, 0.5f, 1f);
+ this.flameParent.transform.localEulerAngles = new Vector3(0f, 0f, -15f);
+ yield return wait;
+ this.flameParent.transform.localScale = new Vector3(1f, 1f, 1f);
+ this.flameParent.transform.localEulerAngles = new Vector3(0f, 0f, 0f);
+ anim.gameObject.SetActive(true);
+ yield return anim.WaitForFinish();
+ UnityEngine.Object.Destroy(anim.gameObject);
+ yield return new WaitForLerp(0.16666667f, delegate(float t)
+ {
+ this.flameParent.transform.localScale = new Vector3(1f, 1f - t, 1f);
+ });
+ this.flameParent.SetActive(false);
+ this.showOne = null;
+ yield break;
+ }
+}
diff --git a/Client/Assembly-CSharp/LanguageButton.cs b/Client/Assembly-CSharp/LanguageButton.cs
new file mode 100644
index 0000000..3d89dda
--- /dev/null
+++ b/Client/Assembly-CSharp/LanguageButton.cs
@@ -0,0 +1,12 @@
+using System;
+using UnityEngine;
+
+public class LanguageButton : MonoBehaviour
+{
+ public TextRenderer Title;
+
+ public PassiveButton Button;
+
+ [HideInInspector]
+ public TextAsset Language;
+}
diff --git a/Client/Assembly-CSharp/LanguageSetter.cs b/Client/Assembly-CSharp/LanguageSetter.cs
new file mode 100644
index 0000000..e5ccac7
--- /dev/null
+++ b/Client/Assembly-CSharp/LanguageSetter.cs
@@ -0,0 +1,50 @@
+using System;
+using UnityEngine;
+
+public class LanguageSetter : MonoBehaviour
+{
+ public LanguageButton ButtonPrefab;
+
+ public Scroller ButtonParent;
+
+ public float ButtonStart = 0.5f;
+
+ public float ButtonHeight = 0.5f;
+
+ private LanguageButton[] AllButtons;
+
+ public void Start()
+ {
+ TextAsset[] languages = DestroyableSingleton<TranslationController>.Instance.Languages;
+ Vector3 vector = new Vector3(0f, this.ButtonStart, -1f);
+ this.AllButtons = new LanguageButton[languages.Length];
+ for (int i = 0; i < languages.Length; i++)
+ {
+ LanguageButton button = UnityEngine.Object.Instantiate<LanguageButton>(this.ButtonPrefab, this.ButtonParent.Inner);
+ this.AllButtons[i] = button;
+ button.Language = languages[i];
+ button.Title.Text = languages[i].name;
+ if ((long)i == (long)((ulong)SaveManager.LastLanguage))
+ {
+ button.Title.Color = Color.green;
+ }
+ button.Button.OnClick.AddListener(delegate()
+ {
+ this.SetLanguage(button);
+ });
+ button.transform.localPosition = vector;
+ vector.y -= this.ButtonHeight;
+ }
+ this.ButtonParent.YBounds.max = Mathf.Max(0f, -vector.y - this.ButtonStart * 2f);
+ }
+
+ public void SetLanguage(LanguageButton selected)
+ {
+ for (int i = 0; i < this.AllButtons.Length; i++)
+ {
+ this.AllButtons[i].Title.Color = Color.white;
+ }
+ selected.Title.Color = Color.green;
+ DestroyableSingleton<TranslationController>.Instance.SetLanguage(selected.Language);
+ }
+}
diff --git a/Client/Assembly-CSharp/LanguageUnit.cs b/Client/Assembly-CSharp/LanguageUnit.cs
new file mode 100644
index 0000000..62ae51e
--- /dev/null
+++ b/Client/Assembly-CSharp/LanguageUnit.cs
@@ -0,0 +1,79 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using UnityEngine;
+
+public class LanguageUnit
+{
+ public bool IsEnglish;
+
+ private Dictionary<StringNames, string> AllStrings = new Dictionary<StringNames, string>();
+
+ private Dictionary<ImageNames, Sprite> AllImages = new Dictionary<ImageNames, Sprite>();
+
+ public LanguageUnit(TextAsset data, ImageData[] images)
+ {
+ foreach (ImageData imageData in images)
+ {
+ this.AllImages.Add(imageData.Name, imageData.Sprite);
+ }
+ using (StringReader stringReader = new StringReader(data.text))
+ {
+ for (string text = stringReader.ReadLine(); text != null; text = stringReader.ReadLine())
+ {
+ if (text.Length != 0)
+ {
+ int num = text.IndexOf(',');
+ if (num < 0)
+ {
+ Debug.LogWarning("Couldn't parse: " + text);
+ }
+ else
+ {
+ string text2 = text.Substring(0, num);
+ StringNames key;
+ if (!Enum.TryParse<StringNames>(text2, out key))
+ {
+ Debug.LogWarning("Couldn't parse: " + text2);
+ }
+ else
+ {
+ string value = LanguageUnit.UnescapeCodes(text.Substring(num + 1));
+ this.AllStrings.Add(key, value);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public static string UnescapeCodes(string src)
+ {
+ if (src.IndexOf("\\n") < 0)
+ {
+ return src;
+ }
+ return src.Replace("\\n", "\n");
+ }
+
+ public string GetString(StringNames stringId, params object[] parts)
+ {
+ string text;
+ if (!this.AllStrings.TryGetValue(stringId, out text))
+ {
+ return "STRMISS";
+ }
+ if (parts.Length != 0)
+ {
+ return string.Format(text, parts);
+ }
+ return text;
+ }
+
+ public Sprite GetImage(ImageNames id)
+ {
+ Sprite result;
+ this.AllImages.TryGetValue(id, out result);
+ return result;
+ }
+}
diff --git a/Client/Assembly-CSharp/LeafBehaviour.cs b/Client/Assembly-CSharp/LeafBehaviour.cs
new file mode 100644
index 0000000..58e2b0a
--- /dev/null
+++ b/Client/Assembly-CSharp/LeafBehaviour.cs
@@ -0,0 +1,40 @@
+using System;
+using UnityEngine;
+
+public class LeafBehaviour : MonoBehaviour
+{
+ public Sprite[] Images;
+
+ public FloatRange SpinSpeed = new FloatRange(-45f, 45f);
+
+ public Vector2Range StartVel;
+
+ public float AccelRate = 30f;
+
+ [HideInInspector]
+ public LeafMinigame Parent;
+
+ public bool Held;
+
+ private static RandomFill<Sprite> ImageFiller = new RandomFill<Sprite>();
+
+ [HideInInspector]
+ public Rigidbody2D body;
+
+ public void Start()
+ {
+ LeafBehaviour.ImageFiller.Set(this.Images);
+ base.GetComponent<SpriteRenderer>().sprite = LeafBehaviour.ImageFiller.Get();
+ this.body = base.GetComponent<Rigidbody2D>();
+ this.body.angularVelocity = this.SpinSpeed.Next();
+ this.body.velocity = this.StartVel.Next();
+ }
+
+ public void FixedUpdate()
+ {
+ if (!this.Held && (double)base.transform.localPosition.x < -2.5)
+ {
+ this.Parent.LeafDone(this);
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/LeafMinigame.cs b/Client/Assembly-CSharp/LeafMinigame.cs
new file mode 100644
index 0000000..17f4d18
--- /dev/null
+++ b/Client/Assembly-CSharp/LeafMinigame.cs
@@ -0,0 +1,104 @@
+using System;
+using PowerTools;
+using UnityEngine;
+
+public class LeafMinigame : Minigame
+{
+ public LeafBehaviour LeafPrefab;
+
+ public Vector2Range ValidArea;
+
+ public SpriteAnim[] Arrows;
+
+ public AnimationClip[] Inactive;
+
+ public AnimationClip[] Active;
+
+ public AnimationClip[] Complete;
+
+ private Collider2D[] Leaves;
+
+ public AudioClip[] LeaveSounds;
+
+ public AudioClip[] SuckSounds;
+
+ private Controller myController = new Controller();
+
+ public override void Begin(PlayerTask task)
+ {
+ base.Begin(task);
+ this.Leaves = new Collider2D[this.MyNormTask.MaxStep - this.MyNormTask.taskStep];
+ for (int i = 0; i < this.Leaves.Length; i++)
+ {
+ LeafBehaviour leafBehaviour = UnityEngine.Object.Instantiate<LeafBehaviour>(this.LeafPrefab);
+ leafBehaviour.transform.SetParent(base.transform);
+ leafBehaviour.Parent = this;
+ Vector3 localPosition = this.ValidArea.Next();
+ localPosition.z = -1f;
+ leafBehaviour.transform.localPosition = localPosition;
+ this.Leaves[i] = leafBehaviour.GetComponent<Collider2D>();
+ }
+ }
+
+ public void FixedUpdate()
+ {
+ this.myController.Update();
+ for (int i = 0; i < this.Leaves.Length; i++)
+ {
+ Collider2D collider2D = this.Leaves[i];
+ if (collider2D)
+ {
+ LeafBehaviour component = collider2D.GetComponent<LeafBehaviour>();
+ switch (this.myController.CheckDrag(collider2D, false))
+ {
+ case DragState.TouchStart:
+ if (Constants.ShouldPlaySfx())
+ {
+ SoundManager.Instance.PlaySound(this.LeaveSounds.Random<AudioClip>(), false, 1f);
+ }
+ for (int j = 0; j < this.Arrows.Length; j++)
+ {
+ this.Arrows[j].Play(this.Active[j], 1f);
+ }
+ component.Held = true;
+ break;
+ case DragState.Dragging:
+ {
+ Vector2 vector = this.myController.DragPosition - component.body.position;
+ component.body.velocity = vector.normalized * Mathf.Min(3f, vector.magnitude * 3f);
+ break;
+ }
+ case DragState.Released:
+ component.Held = false;
+ for (int k = 0; k < this.Arrows.Length; k++)
+ {
+ this.Arrows[k].Play(this.Inactive[k], 1f);
+ this.Arrows[k].GetComponent<SpriteRenderer>().sprite = null;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ public void LeafDone(LeafBehaviour leaf)
+ {
+ if (Constants.ShouldPlaySfx())
+ {
+ SoundManager.Instance.PlaySound(this.SuckSounds.Random<AudioClip>(), false, 1f);
+ }
+ UnityEngine.Object.Destroy(leaf.gameObject);
+ if (this.MyNormTask)
+ {
+ this.MyNormTask.NextStep();
+ if (this.MyNormTask.IsComplete)
+ {
+ for (int i = 0; i < this.Arrows.Length; i++)
+ {
+ this.Arrows[i].Play(this.Complete[i], 1f);
+ }
+ base.StartCoroutine(base.CoStartClose(0.75f));
+ }
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/LetterTree.cs b/Client/Assembly-CSharp/LetterTree.cs
new file mode 100644
index 0000000..b92f743
--- /dev/null
+++ b/Client/Assembly-CSharp/LetterTree.cs
@@ -0,0 +1,299 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+public class LetterTree
+{
+ private LetterTree.LetterNode root = new LetterTree.LetterNode('\0');
+
+ private enum NodeTypes : byte
+ {
+ NonTerm,
+ Terminal,
+ TerminalStrict,
+ TerminalExact,
+ TerminalUnbroken
+ }
+
+ private class LetterNode
+ {
+ public char Letter;
+
+ public LetterTree.NodeTypes Terminal;
+
+ public LetterTree.LetterNode[] Children = new LetterTree.LetterNode[26];
+
+ public LetterNode(char l)
+ {
+ this.Letter = l;
+ }
+
+ public LetterTree.LetterNode CreateChild(char l)
+ {
+ int num = LetterTree.LetterNode.ToIndex(l);
+ LetterTree.LetterNode letterNode = this.Children[num];
+ if (letterNode == null)
+ {
+ letterNode = (this.Children[num] = new LetterTree.LetterNode(l));
+ }
+ return letterNode;
+ }
+
+ public LetterTree.LetterNode FindChild(char l)
+ {
+ int num = LetterTree.LetterNode.ToIndex(l);
+ return this.Children[num];
+ }
+
+ public static int ToIndex(char c)
+ {
+ if (c >= 'A' && c <= 'Z')
+ {
+ return (int)(c - 'A');
+ }
+ if (c >= 'a' && c <= 'z')
+ {
+ return (int)(c - 'a');
+ }
+ if (c == 'с')
+ {
+ return 2;
+ }
+ if (c == 'к')
+ {
+ return 10;
+ }
+ if (c == '$')
+ {
+ return 18;
+ }
+ if (c == '+')
+ {
+ return 19;
+ }
+ if (c == '0')
+ {
+ return 14;
+ }
+ if (c == '1')
+ {
+ return 8;
+ }
+ if (c == '!')
+ {
+ return 8;
+ }
+ if (c == '2')
+ {
+ return 18;
+ }
+ if (c == '3')
+ {
+ return 4;
+ }
+ if (c == '4')
+ {
+ return 0;
+ }
+ if (c == '5')
+ {
+ return 18;
+ }
+ if (c == '7')
+ {
+ return 19;
+ }
+ if (c == '8')
+ {
+ return 1;
+ }
+ if (c > 'z')
+ {
+ foreach (char c2 in c.ToString().Normalize(NormalizationForm.FormD))
+ {
+ if (c2 <= 'z')
+ {
+ return LetterTree.LetterNode.ToIndex(c2);
+ }
+ }
+ }
+ return (int)c;
+ }
+ }
+
+ public void Clear()
+ {
+ this.root = new LetterTree.LetterNode('\0');
+ }
+
+ public void AddWord(string word)
+ {
+ LetterTree.LetterNode letterNode = this.root;
+ foreach (char l in word)
+ {
+ if (!this.IsFiller(l))
+ {
+ letterNode = letterNode.CreateChild(l);
+ }
+ }
+ if (letterNode.Terminal == LetterTree.NodeTypes.NonTerm)
+ {
+ letterNode.Terminal = LetterTree.NodeTypes.Terminal;
+ if (word[word.Length - 1] == '~')
+ {
+ letterNode.Terminal = LetterTree.NodeTypes.TerminalStrict;
+ }
+ if (word[word.Length - 1] == '^')
+ {
+ letterNode.Terminal = LetterTree.NodeTypes.TerminalExact;
+ }
+ if (word[word.Length - 1] == '`')
+ {
+ letterNode.Terminal = LetterTree.NodeTypes.TerminalUnbroken;
+ }
+ }
+ }
+
+ public bool IsFiller(char l)
+ {
+ return LetterTree.LetterNode.ToIndex(l) == (int)l;
+ }
+
+ public int Search(StringBuilder input, int start)
+ {
+ if (start >= input.Length || this.IsFiller(input[start]))
+ {
+ return 0;
+ }
+ bool exactStart = start == 0 || this.IsFiller(input[start - 1]);
+ return this.SubSearchRec(input, start, this.root, false, false, exactStart);
+ }
+
+ public int Search(string inputStr, int start)
+ {
+ StringBuilder stringBuilder = new StringBuilder(inputStr);
+ if (start >= stringBuilder.Length || this.IsFiller(stringBuilder[start]))
+ {
+ return 0;
+ }
+ bool exactStart = start == 0 || this.IsFiller(stringBuilder[start - 1]);
+ return this.SubSearchRec(stringBuilder, start, this.root, false, false, exactStart);
+ }
+
+ private int SubSearchRec(StringBuilder input, int start, LetterTree.LetterNode previous, bool postDupes, bool postBreak, bool exactStart)
+ {
+ if (start >= input.Length)
+ {
+ return -2;
+ }
+ char c = input[start];
+ if (this.IsFiller(c))
+ {
+ if (postDupes)
+ {
+ return -2;
+ }
+ int num = this.SubSearchRec(input, start + 1, previous, postDupes, true, exactStart);
+ if (num > 0)
+ {
+ return num + 1;
+ }
+ return -2;
+ }
+ else
+ {
+ if (c == previous.Letter && !postBreak)
+ {
+ int num2 = this.SubSearchRec(input, start + 1, previous, true, postBreak, exactStart);
+ if (num2 > 0)
+ {
+ return num2 + 1;
+ }
+ if (previous.Terminal != LetterTree.NodeTypes.NonTerm)
+ {
+ return 1;
+ }
+ }
+ LetterTree.LetterNode letterNode = previous.FindChild(c);
+ if (letterNode == null)
+ {
+ return -3;
+ }
+ int num3 = this.SubSearchRec(input, start + 1, letterNode, postDupes, postBreak, exactStart);
+ if (num3 > 0)
+ {
+ return num3 + 1;
+ }
+ if (letterNode.Terminal == LetterTree.NodeTypes.TerminalStrict && num3 == -2 && (exactStart || !postBreak))
+ {
+ return 1;
+ }
+ if (letterNode.Terminal == LetterTree.NodeTypes.TerminalUnbroken && num3 == -2 && !postBreak)
+ {
+ return 1;
+ }
+ if (letterNode.Terminal == LetterTree.NodeTypes.TerminalExact && (num3 == -2 && exactStart))
+ {
+ return 1;
+ }
+ if (letterNode.Terminal == LetterTree.NodeTypes.Terminal && num3 <= 0)
+ {
+ return 1;
+ }
+ return num3;
+ }
+ }
+
+ public IEnumerable<string> GetWords()
+ {
+ StringBuilder b = new StringBuilder();
+ foreach (LetterTree.LetterNode node in this.root.Children)
+ {
+ foreach (string text in this.GetWords(b, 0, node))
+ {
+ yield return text;
+ }
+ IEnumerator<string> enumerator = null;
+ }
+ LetterTree.LetterNode[] array = null;
+ yield break;
+ yield break;
+ }
+
+ private IEnumerable<string> GetWords(StringBuilder b, int i, LetterTree.LetterNode node)
+ {
+ if (node == null)
+ {
+ yield break;
+ }
+ int length = b.Length;
+ b.Length = length + 1;
+ b[i] = node.Letter;
+ if (node.Terminal == LetterTree.NodeTypes.Terminal)
+ {
+ yield return b.ToString();
+ }
+ else if (node.Terminal == LetterTree.NodeTypes.TerminalStrict)
+ {
+ length = b.Length;
+ b.Length = length + 1;
+ b[i + 1] = '~';
+ yield return b.ToString();
+ length = b.Length;
+ b.Length = length - 1;
+ }
+ foreach (LetterTree.LetterNode node2 in node.Children)
+ {
+ foreach (string text in this.GetWords(b, i + 1, node2))
+ {
+ yield return text;
+ }
+ IEnumerator<string> enumerator = null;
+ }
+ LetterTree.LetterNode[] array = null;
+ length = b.Length;
+ b.Length = length - 1;
+ yield break;
+ yield break;
+ }
+}
diff --git a/Client/Assembly-CSharp/LifeSuppSystemType.cs b/Client/Assembly-CSharp/LifeSuppSystemType.cs
new file mode 100644
index 0000000..2e77cfc
--- /dev/null
+++ b/Client/Assembly-CSharp/LifeSuppSystemType.cs
@@ -0,0 +1,121 @@
+using System;
+using System.Collections.Generic;
+using Hazel;
+
+public class LifeSuppSystemType : ISystemType, IActivatable
+{
+ public int UserCount
+ {
+ get
+ {
+ return this.CompletedConsoles.Count;
+ }
+ }
+
+ public bool IsActive
+ {
+ get
+ {
+ return this.Countdown < 10000f;
+ }
+ }
+
+ private const float SyncRate = 2f;
+
+ private float timer;
+
+ public const byte StartCountdown = 128;
+
+ public const byte AddUserOp = 64;
+
+ public const byte ClearCountdown = 16;
+
+ public const float CountdownStopped = 10000f;
+
+ public const float LifeSuppDuration = 45f;
+
+ public const byte ConsoleIdMask = 3;
+
+ public const byte RequiredUserCount = 2;
+
+ public float Countdown = 10000f;
+
+ private HashSet<int> CompletedConsoles = new HashSet<int>();
+
+ public bool GetConsoleComplete(int consoleId)
+ {
+ return this.CompletedConsoles.Contains(consoleId);
+ }
+
+ public void RepairDamage(PlayerControl player, byte opCode)
+ {
+ int item = (int)(opCode & 3);
+ if (opCode == 128 && !this.IsActive)
+ {
+ this.Countdown = 45f;
+ this.CompletedConsoles.Clear();
+ return;
+ }
+ if (opCode == 16)
+ {
+ this.Countdown = 10000f;
+ return;
+ }
+ if (opCode.HasAnyBit(64))
+ {
+ this.CompletedConsoles.Add(item);
+ }
+ }
+
+ public bool Detoriorate(float deltaTime)
+ {
+ if (this.IsActive)
+ {
+ if (DestroyableSingleton<HudManager>.Instance.OxyFlash == null)
+ {
+ PlayerControl.LocalPlayer.AddSystemTask(SystemTypes.LifeSupp);
+ }
+ this.Countdown -= deltaTime;
+ if (this.UserCount >= 2)
+ {
+ this.Countdown = 10000f;
+ return true;
+ }
+ this.timer += deltaTime;
+ if (this.timer > 2f)
+ {
+ this.timer = 0f;
+ return true;
+ }
+ }
+ else if (DestroyableSingleton<HudManager>.Instance.OxyFlash != null)
+ {
+ DestroyableSingleton<HudManager>.Instance.StopOxyFlash();
+ }
+ return false;
+ }
+
+ public void Serialize(MessageWriter writer, bool initialState)
+ {
+ writer.Write(this.Countdown);
+ writer.WritePacked(this.CompletedConsoles.Count);
+ foreach (int value in this.CompletedConsoles)
+ {
+ writer.WritePacked(value);
+ }
+ }
+
+ public void Deserialize(MessageReader reader, bool initialState)
+ {
+ this.Countdown = reader.ReadSingle();
+ if (reader.Position < reader.Length)
+ {
+ this.CompletedConsoles.Clear();
+ int num = reader.ReadPackedInt32();
+ for (int i = 0; i < num; i++)
+ {
+ this.CompletedConsoles.Add(reader.ReadPackedInt32());
+ }
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/LightSource.cs b/Client/Assembly-CSharp/LightSource.cs
new file mode 100644
index 0000000..891fcbf
--- /dev/null
+++ b/Client/Assembly-CSharp/LightSource.cs
@@ -0,0 +1,335 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class LightSource : MonoBehaviour
+{
+ public static Dictionary<GameObject, NoShadowBehaviour> NoShadows = new Dictionary<GameObject, NoShadowBehaviour>();
+
+ public static Dictionary<GameObject, OneWayShadows> OneWayShadows = new Dictionary<GameObject, OneWayShadows>();
+
+ [HideInInspector]
+ private GameObject child;
+
+ [HideInInspector]
+ private Vector2[] requiredDels;
+
+ [HideInInspector]
+ private Mesh myMesh;
+
+ public int MinRays = 24;
+
+ public float LightRadius = 3f;
+
+ public Material Material;
+
+ [HideInInspector]
+ private List<LightSource.VertInfo> verts = new List<LightSource.VertInfo>(256);
+
+ [HideInInspector]
+ private int vertCount;
+
+ private RaycastHit2D[] buffer = new RaycastHit2D[25];
+
+ private Collider2D[] hits = new Collider2D[40];
+
+ private ContactFilter2D filter;
+
+ private Vector3[] vec;
+
+ private Vector2[] uvs;
+
+ private int[] triangles = new int[1200];
+
+ public float tol = 0.05f;
+
+ private Vector2 del;
+
+ private Vector2 tan;
+
+ private Vector2 side;
+
+ private List<RaycastHit2D> lightHits = new List<RaycastHit2D>();
+
+ private class VertInfo
+ {
+ public float Angle;
+
+ public Vector3 Position;
+
+ internal void Complete(float x, float y)
+ {
+ this.Position.x = x;
+ this.Position.y = y;
+ this.Angle = LightSource.pseudoAngle(y, x);
+ }
+
+ internal void Complete(Vector2 point)
+ {
+ this.Position.x = point.x;
+ this.Position.y = point.y;
+ this.Angle = LightSource.pseudoAngle(point.y, point.x);
+ }
+ }
+
+ private class AngleComparer : IComparer<LightSource.VertInfo>
+ {
+ public static readonly LightSource.AngleComparer Instance = new LightSource.AngleComparer();
+
+ public int Compare(LightSource.VertInfo x, LightSource.VertInfo y)
+ {
+ if (x.Angle > y.Angle)
+ {
+ return 1;
+ }
+ if (x.Angle >= y.Angle)
+ {
+ return 0;
+ }
+ return -1;
+ }
+ }
+
+ private class HitDepthComparer : IComparer<RaycastHit2D>
+ {
+ public static readonly LightSource.HitDepthComparer Instance = new LightSource.HitDepthComparer();
+
+ public int Compare(RaycastHit2D x, RaycastHit2D y)
+ {
+ if (x.fraction <= y.fraction)
+ {
+ return -1;
+ }
+ return 1;
+ }
+ }
+
+ private void Start()
+ {
+ this.filter.useTriggers = true;
+ this.filter.layerMask = Constants.ShadowMask;
+ this.filter.useLayerMask = true;
+ this.requiredDels = new Vector2[this.MinRays];
+ for (int i = 0; i < this.requiredDels.Length; i++)
+ {
+ this.requiredDels[i] = Vector2.left.Rotate((float)i / (float)this.requiredDels.Length * 360f);
+ }
+ this.myMesh = new Mesh();
+ this.myMesh.MarkDynamic();
+ this.myMesh.name = "ShadowMesh";
+ GameObject gameObject = new GameObject("LightChild");
+ gameObject.layer = 10;
+ gameObject.AddComponent<MeshFilter>().mesh = this.myMesh;
+ Renderer renderer = gameObject.AddComponent<MeshRenderer>();
+ this.Material = new Material(this.Material);
+ renderer.sharedMaterial = this.Material;
+ this.child = gameObject;
+ }
+
+ private void Update()
+ {
+ this.vertCount = 0;
+ Vector3 position = base.transform.position;
+ position.z -= 7f;
+ this.child.transform.position = position;
+ Vector2 vector = position;
+ this.Material.SetFloat("_LightRadius", this.LightRadius);
+ int num = Physics2D.OverlapCircleNonAlloc(vector, this.LightRadius, this.hits, Constants.ShadowMask);
+ for (int i = 0; i < num; i++)
+ {
+ Collider2D collider2D = this.hits[i];
+ if (!collider2D.isTrigger)
+ {
+ EdgeCollider2D edgeCollider2D = collider2D as EdgeCollider2D;
+ if (edgeCollider2D)
+ {
+ Vector2[] points = edgeCollider2D.points;
+ for (int j = 0; j < points.Length; j++)
+ {
+ Vector2 vector2 = edgeCollider2D.transform.TransformPoint(points[j]);
+ this.del.x = vector2.x - vector.x;
+ this.del.y = vector2.y - vector.y;
+ this.TestBothSides(vector);
+ }
+ }
+ else
+ {
+ PolygonCollider2D polygonCollider2D = collider2D as PolygonCollider2D;
+ if (polygonCollider2D)
+ {
+ Vector2[] points2 = polygonCollider2D.points;
+ for (int k = 0; k < points2.Length; k++)
+ {
+ Vector2 vector3 = polygonCollider2D.transform.TransformPoint(points2[k]);
+ this.del.x = vector3.x - vector.x;
+ this.del.y = vector3.y - vector.y;
+ this.TestBothSides(vector);
+ }
+ }
+ else
+ {
+ BoxCollider2D boxCollider2D = collider2D as BoxCollider2D;
+ if (boxCollider2D)
+ {
+ Vector2 b = boxCollider2D.size / 2f;
+ Vector2 vector4 = boxCollider2D.transform.TransformPoint(boxCollider2D.offset - b) - vector;
+ Vector2 vector5 = boxCollider2D.transform.TransformPoint(boxCollider2D.offset + b) - vector;
+ this.del.x = vector4.x;
+ this.del.y = vector4.y;
+ this.TestBothSides(vector);
+ this.del.x = vector5.x;
+ this.TestBothSides(vector);
+ this.del.y = vector5.y;
+ this.TestBothSides(vector);
+ this.del.x = vector4.x;
+ this.TestBothSides(vector);
+ }
+ }
+ }
+ }
+ }
+ float d = this.LightRadius * 1.05f;
+ for (int l = 0; l < this.requiredDels.Length; l++)
+ {
+ Vector2 vector6 = d * this.requiredDels[l];
+ this.CreateVert(vector, ref vector6);
+ }
+ this.verts.Sort(0, this.vertCount, LightSource.AngleComparer.Instance);
+ this.myMesh.Clear();
+ if (this.vec == null || this.vec.Length < this.vertCount + 1)
+ {
+ this.vec = new Vector3[this.vertCount + 1];
+ this.uvs = new Vector2[this.vec.Length];
+ }
+ this.vec[0] = Vector3.zero;
+ this.uvs[0] = new Vector2(this.vec[0].x, this.vec[0].y);
+ for (int m = 0; m < this.vertCount; m++)
+ {
+ int num2 = m + 1;
+ this.vec[num2] = this.verts[m].Position;
+ this.uvs[num2] = new Vector2(this.vec[num2].x, this.vec[num2].y);
+ }
+ int num3 = this.vertCount * 3;
+ if (num3 > this.triangles.Length)
+ {
+ this.triangles = new int[num3];
+ Debug.LogWarning("Resized triangles to: " + num3);
+ }
+ int num4 = 0;
+ for (int n = 0; n < this.triangles.Length; n += 3)
+ {
+ if (n < num3)
+ {
+ this.triangles[n] = 0;
+ this.triangles[n + 1] = num4 + 1;
+ if (n == num3 - 3)
+ {
+ this.triangles[n + 2] = 1;
+ }
+ else
+ {
+ this.triangles[n + 2] = num4 + 2;
+ }
+ num4++;
+ }
+ else
+ {
+ this.triangles[n] = 0;
+ this.triangles[n + 1] = 0;
+ this.triangles[n + 2] = 0;
+ }
+ }
+ this.myMesh.vertices = this.vec;
+ this.myMesh.uv = this.uvs;
+ this.myMesh.SetIndices(this.triangles, MeshTopology.Triangles, 0);
+ }
+
+ private void TestBothSides(Vector2 myPos)
+ {
+ float num = LightSource.length(this.del.x, this.del.x);
+ this.tan.x = -this.del.y / num * this.tol;
+ this.tan.y = this.del.x / num * this.tol;
+ this.side.x = this.del.x + this.tan.x;
+ this.side.y = this.del.y + this.tan.y;
+ this.CreateVert(myPos, ref this.side);
+ this.side.x = this.del.x - this.tan.x;
+ this.side.y = this.del.y - this.tan.y;
+ this.CreateVert(myPos, ref this.side);
+ }
+
+ private void CreateVert(Vector2 myPos, ref Vector2 del)
+ {
+ float num = this.LightRadius * 1.5f;
+ int num2 = Physics2D.Raycast(myPos, del, this.filter, this.buffer, num);
+ if (num2 > 0)
+ {
+ this.lightHits.Clear();
+ RaycastHit2D raycastHit2D = default(RaycastHit2D);
+ Collider2D collider2D = null;
+ for (int i = 0; i < num2; i++)
+ {
+ RaycastHit2D raycastHit2D2 = this.buffer[i];
+ Collider2D collider = raycastHit2D2.collider;
+ OneWayShadows oneWayShadows;
+ if (!LightSource.OneWayShadows.TryGetValue(collider.gameObject, out oneWayShadows) || !oneWayShadows.IsIgnored(this))
+ {
+ this.lightHits.Add(raycastHit2D2);
+ if (!collider.isTrigger)
+ {
+ raycastHit2D = raycastHit2D2;
+ collider2D = collider;
+ break;
+ }
+ }
+ }
+ for (int j = 0; j < this.lightHits.Count; j++)
+ {
+ NoShadowBehaviour noShadowBehaviour;
+ if (LightSource.NoShadows.TryGetValue(this.lightHits[j].collider.gameObject, out noShadowBehaviour))
+ {
+ noShadowBehaviour.didHit = true;
+ }
+ }
+ if (collider2D && !collider2D.isTrigger)
+ {
+ Vector2 point = raycastHit2D.point;
+ this.GetEmptyVert().Complete(point.x - myPos.x, point.y - myPos.y);
+ return;
+ }
+ }
+ Vector2 normalized = del.normalized;
+ this.GetEmptyVert().Complete(normalized.x * num, normalized.y * num);
+ }
+
+ private LightSource.VertInfo GetEmptyVert()
+ {
+ if (this.vertCount < this.verts.Count)
+ {
+ List<LightSource.VertInfo> list = this.verts;
+ int num = this.vertCount;
+ this.vertCount = num + 1;
+ return list[num];
+ }
+ LightSource.VertInfo vertInfo = new LightSource.VertInfo();
+ this.verts.Add(vertInfo);
+ this.vertCount = this.verts.Count;
+ return vertInfo;
+ }
+
+ private static float length(float x, float y)
+ {
+ return Mathf.Sqrt(x * x + y * y);
+ }
+
+ public static float pseudoAngle(float dx, float dy)
+ {
+ if (dx < 0f)
+ {
+ float num = -dx;
+ float num2 = (dy > 0f) ? dy : (-dy);
+ return 2f - dy / (num + num2);
+ }
+ float num3 = (dy > 0f) ? dy : (-dy);
+ return dy / (dx + num3);
+ }
+}
diff --git a/Client/Assembly-CSharp/LobbyBehaviour.cs b/Client/Assembly-CSharp/LobbyBehaviour.cs
new file mode 100644
index 0000000..de036b7
--- /dev/null
+++ b/Client/Assembly-CSharp/LobbyBehaviour.cs
@@ -0,0 +1,82 @@
+using System;
+using Hazel;
+using InnerNet;
+using UnityEngine;
+
+public class LobbyBehaviour : InnerNetObject
+{
+ public static LobbyBehaviour Instance;
+
+ public AudioClip SpawnSound;
+
+ public AnimationClip SpawnInClip;
+
+ public Vector2[] SpawnPositions;
+
+ public AudioClip DropShipSound;
+
+ public ShipRoom[] AllRooms;
+
+ private float timer;
+
+ public void Start()
+ {
+ LobbyBehaviour.Instance = this;
+ SoundManager.Instance.StopAllSound();
+ SoundManager.Instance.PlaySound(this.DropShipSound, true, 1f).pitch = 1.2f;
+ Camera main = Camera.main;
+ if (main)
+ {
+ FollowerCamera component = main.GetComponent<FollowerCamera>();
+ if (component)
+ {
+ component.shakeAmount = 0.03f;
+ component.shakePeriod = 400f;
+ }
+ }
+ }
+
+ public void FixedUpdate()
+ {
+ this.timer += Time.deltaTime;
+ if (this.timer < 0.25f)
+ {
+ return;
+ }
+ this.timer = 0f;
+ if (PlayerControl.GameOptions != null)
+ {
+ int numPlayers = GameData.Instance ? GameData.Instance.PlayerCount : 10;
+ DestroyableSingleton<HudManager>.Instance.GameSettings.Text = PlayerControl.GameOptions.ToHudString(numPlayers);
+ DestroyableSingleton<HudManager>.Instance.GameSettings.gameObject.SetActive(true);
+ }
+ }
+
+ public override void OnDestroy()
+ {
+ Camera main = Camera.main;
+ if (main)
+ {
+ FollowerCamera component = main.GetComponent<FollowerCamera>();
+ if (component)
+ {
+ component.shakeAmount = 0.02f;
+ component.shakePeriod = 0.3f;
+ }
+ }
+ base.OnDestroy();
+ }
+
+ public override void HandleRpc(byte callId, MessageReader reader)
+ {
+ }
+
+ public override bool Serialize(MessageWriter writer, bool initialState)
+ {
+ return false;
+ }
+
+ public override void Deserialize(MessageReader reader, bool initialState)
+ {
+ }
+}
diff --git a/Client/Assembly-CSharp/MMOnlineManager.cs b/Client/Assembly-CSharp/MMOnlineManager.cs
new file mode 100644
index 0000000..f65820c
--- /dev/null
+++ b/Client/Assembly-CSharp/MMOnlineManager.cs
@@ -0,0 +1,28 @@
+using System;
+using UnityEngine;
+
+public class MMOnlineManager : DestroyableSingleton<MMOnlineManager>
+{
+ public GameObject HelpMenu;
+
+ public void Start()
+ {
+ if (this.HelpMenu)
+ {
+ if (SaveManager.ShowOnlineHelp)
+ {
+ SaveManager.ShowOnlineHelp = false;
+ return;
+ }
+ this.HelpMenu.gameObject.SetActive(false);
+ }
+ }
+
+ private void Update()
+ {
+ if (Input.GetKeyUp(KeyCode.Escape))
+ {
+ SceneChanger.ChangeScene("MainMenu");
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/MainMenuManager.cs b/Client/Assembly-CSharp/MainMenuManager.cs
new file mode 100644
index 0000000..c3a2054
--- /dev/null
+++ b/Client/Assembly-CSharp/MainMenuManager.cs
@@ -0,0 +1,66 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.Analytics;
+
+public class MainMenuManager : MonoBehaviour
+{
+ public DataCollectScreen DataPolicy;
+
+ public AdDataCollectScreen AdsPolicy;
+
+ public AnnouncementPopUp Announcement;
+
+ public UnlockPopUp UnlockPop;
+
+ private static bool SentTelemetry;
+
+ public void Start()
+ {
+ if (!MainMenuManager.SentTelemetry && SaveManager.SendTelemetry)
+ {
+ MainMenuManager.SentTelemetry = true;
+ DateTime utcNow = DateTime.UtcNow;
+ if (SaveManager.LastStartDate != DateTime.MinValue && SaveManager.LastStartDate < utcNow)
+ {
+ TimeSpan timeSpan = utcNow - SaveManager.LastStartDate;
+ Analytics.CustomEvent("GameOpened", new Dictionary<string, object>
+ {
+ {
+ "TotalMinutes",
+ timeSpan.TotalMinutes
+ }
+ });
+ }
+ SaveManager.LastStartDate = utcNow;
+ }
+ base.StartCoroutine(this.Announcement.Init());
+ base.StartCoroutine(this.RunStartUp());
+ }
+
+ private IEnumerator RunStartUp()
+ {
+ yield return this.DataPolicy.Show();
+ yield return this.Announcement.Show();
+ yield return this.UnlockPop.Show();
+ DateTime utcNow = DateTime.UtcNow;
+ for (int i = 0; i < DestroyableSingleton<HatManager>.Instance.AllHats.Count; i++)
+ {
+ HatBehaviour hatBehaviour = DestroyableSingleton<HatManager>.Instance.AllHats[i];
+ if ((hatBehaviour.LimitedMonth == utcNow.Month || hatBehaviour.LimitedMonth == 0) && (hatBehaviour.LimitedYear == utcNow.Year || hatBehaviour.LimitedYear == 0) && !SaveManager.GetPurchase(hatBehaviour.ProductId))
+ {
+ SaveManager.SetPurchased(hatBehaviour.ProductId);
+ }
+ }
+ yield break;
+ }
+
+ private void Update()
+ {
+ if (Input.GetKeyUp(KeyCode.Escape))
+ {
+ Application.Quit();
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/ManualDoor.cs b/Client/Assembly-CSharp/ManualDoor.cs
new file mode 100644
index 0000000..fb2ac04
--- /dev/null
+++ b/Client/Assembly-CSharp/ManualDoor.cs
@@ -0,0 +1,90 @@
+using System;
+using System.Collections;
+using Hazel;
+using PowerTools;
+using UnityEngine;
+
+public class ManualDoor : MonoBehaviour
+{
+ private const float ClosedDuration = 10f;
+
+ public const float CooldownDuration = 30f;
+
+ public bool Open;
+
+ public BoxCollider2D myCollider;
+
+ public SpriteAnim animator;
+
+ public AnimationClip OpenDoorAnim;
+
+ public AnimationClip CloseDoorAnim;
+
+ private float size;
+
+ private void Awake()
+ {
+ Vector2 vector = this.myCollider.size;
+ this.size = ((vector.x > vector.y) ? vector.y : vector.x);
+ }
+
+ public virtual void SetDoorway(bool open)
+ {
+ if (this.Open == open)
+ {
+ return;
+ }
+ if (this.animator)
+ {
+ this.animator.Play(open ? this.OpenDoorAnim : this.CloseDoorAnim, 1f);
+ }
+ this.Open = open;
+ this.myCollider.isTrigger = open;
+ base.StopAllCoroutines();
+ if (!open)
+ {
+ Vector2 vector = this.myCollider.size;
+ base.StartCoroutine(this.CoCloseDoorway(vector.x > vector.y));
+ }
+ }
+
+ // 自动关门
+ private IEnumerator CoCloseDoorway(bool isHort)
+ {
+ Vector2 s = this.myCollider.size;
+ float i = 0f;
+ if (isHort)
+ {
+ while (i < 0.1f)
+ {
+ i += Time.deltaTime;
+ s.y = Mathf.Lerp(0.0001f, this.size, i / 0.1f);
+ this.myCollider.size = s;
+ yield return null;
+ }
+ }
+ else
+ {
+ while (i < 0.1f)
+ {
+ i += Time.deltaTime;
+ s.x = Mathf.Lerp(0.0001f, this.size, i / 0.1f);
+ this.myCollider.size = s;
+ yield return null;
+ }
+ }
+ yield break;
+ }
+
+ //c 同步门的状态
+
+ public virtual void Serialize(MessageWriter writer)
+ {
+ writer.Write(this.Open);
+ }
+
+ public virtual void Deserialize(MessageReader reader)
+ {
+ this.SetDoorway(reader.ReadBoolean());
+ }
+}
diff --git a/Client/Assembly-CSharp/MapBehaviour.cs b/Client/Assembly-CSharp/MapBehaviour.cs
new file mode 100644
index 0000000..85d6b39
--- /dev/null
+++ b/Client/Assembly-CSharp/MapBehaviour.cs
@@ -0,0 +1,113 @@
+using System;
+using UnityEngine;
+
+public class MapBehaviour : MonoBehaviour
+{
+ public bool IsOpen
+ {
+ get
+ {
+ return base.isActiveAndEnabled;
+ }
+ }
+
+ public bool IsOpenStopped
+ {
+ get
+ {
+ return this.IsOpen && this.countOverlay.isActiveAndEnabled;
+ }
+ }
+
+ public static MapBehaviour Instance;
+
+ public AlphaPulse ColorControl;
+
+ public SpriteRenderer HerePoint;
+
+ public MapCountOverlay countOverlay;
+
+ public InfectedOverlay infectedOverlay;
+
+ public MapTaskOverlay taskOverlay;
+
+ private void Awake()
+ {
+ MapBehaviour.Instance = this;
+ }
+
+ private void GenericShow()
+ {
+ base.transform.localScale = Vector3.one;
+ base.transform.localPosition = new Vector3(0f, 0f, -25f);
+ base.gameObject.SetActive(true);
+ }
+
+ public void ShowInfectedMap()
+ {
+ if (this.IsOpen)
+ {
+ this.Close();
+ return;
+ }
+ if (!PlayerControl.LocalPlayer.CanMove)
+ {
+ return;
+ }
+ PlayerControl.LocalPlayer.SetPlayerMaterialColors(this.HerePoint);
+ this.GenericShow();
+ this.infectedOverlay.gameObject.SetActive(true);
+ this.ColorControl.SetColor(Palette.ImpostorRed);
+ this.taskOverlay.Hide();
+ DestroyableSingleton<HudManager>.Instance.SetHudActive(false);
+ }
+
+ public void ShowNormalMap()
+ {
+ if (this.IsOpen)
+ {
+ this.Close();
+ return;
+ }
+ if (!PlayerControl.LocalPlayer.CanMove)
+ {
+ return;
+ }
+ PlayerControl.LocalPlayer.SetPlayerMaterialColors(this.HerePoint);
+ this.GenericShow();
+ this.taskOverlay.Show();
+ this.ColorControl.SetColor(new Color(0.05f, 0.2f, 1f, 1f));
+ DestroyableSingleton<HudManager>.Instance.SetHudActive(false);
+ }
+
+ public void ShowCountOverlay()
+ {
+ this.GenericShow();
+ this.countOverlay.gameObject.SetActive(true);
+ this.taskOverlay.Hide();
+ this.HerePoint.enabled = false;
+ DestroyableSingleton<HudManager>.Instance.SetHudActive(false);
+ }
+
+ public void FixedUpdate()
+ {
+ if (!ShipStatus.Instance)
+ {
+ return;
+ }
+ Vector3 vector = PlayerControl.LocalPlayer.transform.position;
+ vector /= ShipStatus.Instance.MapScale;
+ vector.z = -1f;
+ this.HerePoint.transform.localPosition = vector;
+ }
+
+ public void Close()
+ {
+ base.gameObject.SetActive(false);
+ this.countOverlay.gameObject.SetActive(false);
+ this.infectedOverlay.gameObject.SetActive(false);
+ this.taskOverlay.Hide();
+ this.HerePoint.enabled = true;
+ DestroyableSingleton<HudManager>.Instance.SetHudActive(true);
+ }
+}
diff --git a/Client/Assembly-CSharp/MapConsole.cs b/Client/Assembly-CSharp/MapConsole.cs
new file mode 100644
index 0000000..84a2e68
--- /dev/null
+++ b/Client/Assembly-CSharp/MapConsole.cs
@@ -0,0 +1,65 @@
+using System;
+using UnityEngine;
+
+public class MapConsole : MonoBehaviour, IUsable
+{
+ public float UsableDistance
+ {
+ get
+ {
+ return this.usableDistance;
+ }
+ }
+
+ public float PercentCool
+ {
+ get
+ {
+ return 0f;
+ }
+ }
+
+ public float usableDistance = 1f;
+
+ public SpriteRenderer Image;
+
+ public void SetOutline(bool on, bool mainTarget)
+ {
+ if (this.Image)
+ {
+ this.Image.material.SetFloat("_Outline", (float)(on ? 1 : 0));
+ this.Image.material.SetColor("_OutlineColor", Color.white);
+ this.Image.material.SetColor("_AddColor", mainTarget ? Color.white : Color.clear);
+ }
+ }
+
+ public float CanUse(GameData.PlayerInfo pc, out bool canUse, out bool couldUse)
+ {
+ float num = float.MaxValue;
+ PlayerControl @object = pc.Object;
+ couldUse = pc.Object.CanMove;
+ canUse = couldUse;
+ if (canUse)
+ {
+ num = Vector2.Distance(@object.GetTruePosition(), base.transform.position);
+ canUse &= (num <= this.UsableDistance);
+ }
+ return num;
+ }
+
+ public void Use()
+ {
+ bool flag;
+ bool flag2;
+ this.CanUse(PlayerControl.LocalPlayer.Data, out flag, out flag2);
+ if (!flag)
+ {
+ return;
+ }
+ PlayerControl.LocalPlayer.NetTransform.Halt();
+ DestroyableSingleton<HudManager>.Instance.ShowMap(delegate(MapBehaviour m)
+ {
+ m.ShowCountOverlay();
+ });
+ }
+}
diff --git a/Client/Assembly-CSharp/MapCountOverlay.cs b/Client/Assembly-CSharp/MapCountOverlay.cs
new file mode 100644
index 0000000..571b676
--- /dev/null
+++ b/Client/Assembly-CSharp/MapCountOverlay.cs
@@ -0,0 +1,90 @@
+using System;
+using System.Linq;
+using UnityEngine;
+
+public class MapCountOverlay : MonoBehaviour
+{
+ public AlphaPulse BackgroundColor;
+
+ public TextRenderer SabotageText;
+
+ public CounterArea[] CountAreas;
+
+ private Collider2D[] buffer = new Collider2D[20];
+
+ private ContactFilter2D filter;
+
+ private float timer;
+
+ private bool isSab;
+
+ public void Awake()
+ {
+ this.filter.useLayerMask = true;
+ this.filter.layerMask = Constants.PlayersOnlyMask;
+ this.filter.useTriggers = true;
+ }
+
+ public void OnEnable()
+ {
+ this.BackgroundColor.SetColor(PlayerTask.PlayerHasHudTask(PlayerControl.LocalPlayer) ? Palette.DisabledGrey : Color.green);
+ this.timer = 1f;
+ }
+
+ public void OnDisable()
+ {
+ for (int i = 0; i < this.CountAreas.Length; i++)
+ {
+ this.CountAreas[i].UpdateCount(0);
+ }
+ }
+
+ public void Update()
+ {
+ this.timer += Time.deltaTime;
+ if (this.timer < 0.1f)
+ {
+ return;
+ }
+ this.timer = 0f;
+ if (!this.isSab && PlayerTask.PlayerHasHudTask(PlayerControl.LocalPlayer))
+ {
+ this.isSab = true;
+ this.BackgroundColor.SetColor(Palette.DisabledGrey);
+ this.SabotageText.gameObject.SetActive(true);
+ return;
+ }
+ if (this.isSab && !PlayerTask.PlayerHasHudTask(PlayerControl.LocalPlayer))
+ {
+ this.isSab = false;
+ this.BackgroundColor.SetColor(Color.green);
+ this.SabotageText.gameObject.SetActive(false);
+ }
+ for (int i = 0; i < this.CountAreas.Length; i++)
+ {
+ CounterArea area = this.CountAreas[i];
+ if (!PlayerTask.PlayerHasHudTask(PlayerControl.LocalPlayer))
+ {
+ int num = ShipStatus.Instance.AllRooms.First((ShipRoom r) => r.RoomId == area.RoomType).roomArea.OverlapCollider(this.filter, this.buffer);
+ int num2 = num;
+ for (int j = 0; j < num; j++)
+ {
+ Collider2D collider2D = this.buffer[j];
+ if (!(collider2D.tag == "DeadBody"))
+ {
+ PlayerControl component = collider2D.GetComponent<PlayerControl>();
+ if (!component || component.Data == null || component.Data.Disconnected || component.Data.IsDead)
+ {
+ num2--;
+ }
+ }
+ }
+ area.UpdateCount(num2);
+ }
+ else
+ {
+ area.UpdateCount(0);
+ }
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/MapRoom.cs b/Client/Assembly-CSharp/MapRoom.cs
new file mode 100644
index 0000000..c25469c
--- /dev/null
+++ b/Client/Assembly-CSharp/MapRoom.cs
@@ -0,0 +1,92 @@
+using System;
+using UnityEngine;
+
+public class MapRoom : MonoBehaviour
+{
+ public InfectedOverlay Parent { get; set; }
+
+ public SystemTypes room;
+
+ public SpriteRenderer door;
+
+ public SpriteRenderer special;
+
+ public void Start()
+ {
+ if (this.door)
+ {
+ this.door.SetCooldownNormalizedUvs();
+ }
+ if (this.special)
+ {
+ this.special.SetCooldownNormalizedUvs();
+ }
+ }
+
+ public void OOBUpdate()
+ {
+ if (this.door && ShipStatus.Instance)
+ {
+ float timer = ((DoorsSystemType)ShipStatus.Instance.Systems[SystemTypes.Doors]).GetTimer(this.room);
+ float value = this.Parent.CanUseDoors ? (timer / 30f) : 1f;
+ this.door.material.SetFloat("_Percent", value);
+ }
+ }
+
+ internal void SetSpecialActive(float perc)
+ {
+ if (this.special)
+ {
+ this.special.material.SetFloat("_Percent", perc);
+ }
+ }
+
+ public void SabotageReactor()
+ {
+ if (!this.Parent.CanUseSpecial)
+ {
+ return;
+ }
+ ShipStatus.Instance.RpcRepairSystem(SystemTypes.Sabotage, 3);
+ }
+
+ public void SabotageComms()
+ {
+ if (!this.Parent.CanUseSpecial)
+ {
+ return;
+ }
+ ShipStatus.Instance.RpcRepairSystem(SystemTypes.Sabotage, 14);
+ }
+
+ public void SabotageOxygen()
+ {
+ if (!this.Parent.CanUseSpecial)
+ {
+ return;
+ }
+ ShipStatus.Instance.RpcRepairSystem(SystemTypes.Sabotage, 8);
+ }
+
+ public void SabotageLights()
+ {
+ if (!this.Parent.CanUseSpecial)
+ {
+ return;
+ }
+ ShipStatus.Instance.RpcRepairSystem(SystemTypes.Sabotage, 7);
+ }
+
+ public void SabotageDoors()
+ {
+ if (!this.Parent.CanUseDoors)
+ {
+ return;
+ }
+ if (((DoorsSystemType)ShipStatus.Instance.Systems[SystemTypes.Doors]).GetTimer(this.room) > 0f)
+ {
+ return;
+ }
+ ShipStatus.Instance.RpcCloseDoorsOfType(this.room);
+ }
+}
diff --git a/Client/Assembly-CSharp/MapTaskOverlay.cs b/Client/Assembly-CSharp/MapTaskOverlay.cs
new file mode 100644
index 0000000..cc70292
--- /dev/null
+++ b/Client/Assembly-CSharp/MapTaskOverlay.cs
@@ -0,0 +1,101 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class MapTaskOverlay : MonoBehaviour
+{
+ public ObjectPoolBehavior icons;
+
+ private Dictionary<PlayerTask, PooledMapIcon> data = new Dictionary<PlayerTask, PooledMapIcon>();
+
+ public void Show()
+ {
+ base.gameObject.SetActive(true);
+ if (PlayerTask.PlayerHasHudTask(PlayerControl.LocalPlayer))
+ {
+ return;
+ }
+ for (int i = 0; i < PlayerControl.LocalPlayer.myTasks.Count; i++)
+ {
+ PlayerTask playerTask = PlayerControl.LocalPlayer.myTasks[i];
+ if (playerTask.HasLocation && !playerTask.IsComplete)
+ {
+ PooledMapIcon pooledMapIcon = this.icons.Get<PooledMapIcon>();
+ pooledMapIcon.transform.localScale = new Vector3(pooledMapIcon.NormalSize, pooledMapIcon.NormalSize, pooledMapIcon.NormalSize);
+ if (PlayerTask.TaskIsEmergency(playerTask))
+ {
+ pooledMapIcon.rend.color = Color.red;
+ pooledMapIcon.alphaPulse.enabled = true;
+ pooledMapIcon.rend.material.SetFloat("_Outline", 1f);
+ }
+ else
+ {
+ pooledMapIcon.rend.color = Color.yellow;
+ }
+ MapTaskOverlay.SetIconLocation(playerTask, pooledMapIcon);
+ this.data.Add(playerTask, pooledMapIcon);
+ }
+ }
+ }
+
+ public void Update()
+ {
+ if (PlayerTask.PlayerHasHudTask(PlayerControl.LocalPlayer))
+ {
+ return;
+ }
+ for (int i = 0; i < PlayerControl.LocalPlayer.myTasks.Count; i++)
+ {
+ PlayerTask playerTask = PlayerControl.LocalPlayer.myTasks[i];
+ if (playerTask.HasLocation && !playerTask.IsComplete && playerTask.LocationDirty)
+ {
+ PooledMapIcon pooledMapIcon;
+ if (!this.data.TryGetValue(playerTask, out pooledMapIcon))
+ {
+ pooledMapIcon = this.icons.Get<PooledMapIcon>();
+ pooledMapIcon.transform.localScale = new Vector3(0.4f, 0.4f, 0.4f);
+ if (PlayerTask.TaskIsEmergency(playerTask))
+ {
+ pooledMapIcon.rend.color = Color.red;
+ pooledMapIcon.alphaPulse.enabled = true;
+ pooledMapIcon.rend.material.SetFloat("_Outline", 1f);
+ }
+ else
+ {
+ pooledMapIcon.rend.color = Color.yellow;
+ }
+ this.data.Add(playerTask, pooledMapIcon);
+ }
+ MapTaskOverlay.SetIconLocation(playerTask, pooledMapIcon);
+ }
+ }
+ }
+
+ private static void SetIconLocation(PlayerTask task, PooledMapIcon mapIcon)
+ {
+ if (mapIcon.lastMapTaskStep != task.TaskStep)
+ {
+ mapIcon.lastMapTaskStep = task.TaskStep;
+ Vector3 vector = task.Location;
+ vector /= ShipStatus.Instance.MapScale;
+ vector.z = -1f;
+ mapIcon.name = task.name;
+ mapIcon.transform.localPosition = vector;
+ if (task.TaskStep > 0)
+ {
+ mapIcon.alphaPulse.enabled = true;
+ mapIcon.rend.material.SetFloat("_Outline", 1f);
+ }
+ }
+ }
+
+ public void Hide()
+ {
+ foreach (KeyValuePair<PlayerTask, PooledMapIcon> keyValuePair in this.data)
+ {
+ keyValuePair.Value.OwnerPool.Reclaim(keyValuePair.Value);
+ }
+ this.data.Clear();
+ base.gameObject.SetActive(false);
+ }
+}
diff --git a/Client/Assembly-CSharp/MatchMaker.cs b/Client/Assembly-CSharp/MatchMaker.cs
new file mode 100644
index 0000000..8c36a5c
--- /dev/null
+++ b/Client/Assembly-CSharp/MatchMaker.cs
@@ -0,0 +1,41 @@
+using System;
+using InnerNet;
+using UnityEngine;
+
+public class MatchMaker : DestroyableSingleton<MatchMaker>
+{
+ public TextBox NameText;
+
+ public TextBox GameIdText;
+
+ private MonoBehaviour Connecter;
+
+ public void Start()
+ {
+ if (this.GameIdText && AmongUsClient.Instance)
+ {
+ this.GameIdText.SetText(InnerNetClient.IntToGameName(AmongUsClient.Instance.GameId) ?? "", "");
+ }
+ }
+
+ public bool Connecting(MonoBehaviour button)
+ {
+ if (!this.Connecter)
+ {
+ this.Connecter = button;
+ ((IConnectButton)this.Connecter).StartIcon();
+ return true;
+ }
+ base.StartCoroutine(Effects.Shake(this.Connecter.transform, 0.75f, 0.25f));
+ return false;
+ }
+
+ public void NotConnecting()
+ {
+ if (this.Connecter)
+ {
+ ((IConnectButton)this.Connecter).StopIcon();
+ this.Connecter = null;
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/MatchMakerGameButton.cs b/Client/Assembly-CSharp/MatchMakerGameButton.cs
new file mode 100644
index 0000000..64be6de
--- /dev/null
+++ b/Client/Assembly-CSharp/MatchMakerGameButton.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Collections;
+using InnerNet;
+using PowerTools;
+using UnityEngine;
+
+public class MatchMakerGameButton : PoolableBehavior, IConnectButton
+{
+ public TextRenderer NameText;
+
+ public TextRenderer PlayerCountText;
+
+ public TextRenderer ImpostorCountText;
+
+ public SpriteAnim connectIcon;
+
+ public AnimationClip connectClip;
+
+ public GameListing myListing;
+
+ public void OnClick()
+ {
+ if (!DestroyableSingleton<MatchMaker>.Instance.Connecting(this))
+ {
+ return;
+ }
+ AmongUsClient.Instance.GameMode = GameModes.OnlineGame;
+ AmongUsClient.Instance.OnlineScene = "OnlineGame";
+ AmongUsClient.Instance.GameId = this.myListing.GameId;
+ AmongUsClient.Instance.JoinGame();
+ base.StartCoroutine(this.ConnectForFindGame());
+ }
+
+ private IEnumerator ConnectForFindGame()
+ {
+ yield return EndGameManager.WaitWithTimeout(() => AmongUsClient.Instance.ClientId >= 0 || AmongUsClient.Instance.LastDisconnectReason > DisconnectReasons.ExitGame);
+ DestroyableSingleton<MatchMaker>.Instance.NotConnecting();
+ yield break;
+ }
+
+ public void StartIcon()
+ {
+ this.connectIcon.Play(this.connectClip, 1f);
+ }
+
+ public void StopIcon()
+ {
+ this.connectIcon.Stop();
+ this.connectIcon.GetComponent<SpriteRenderer>().sprite = null;
+ }
+
+ public void SetGame(GameListing gameListing)
+ {
+ this.myListing = gameListing;
+ this.NameText.Text = this.myListing.HostName;
+ this.ImpostorCountText.Text = this.myListing.ImpostorCount.ToString();
+ this.PlayerCountText.Text = string.Format("{0}/{1}", this.myListing.PlayerCount, this.myListing.MaxPlayers);
+ }
+}
diff --git a/Client/Assembly-CSharp/MedScanMinigame.cs b/Client/Assembly-CSharp/MedScanMinigame.cs
new file mode 100644
index 0000000..df940e2
--- /dev/null
+++ b/Client/Assembly-CSharp/MedScanMinigame.cs
@@ -0,0 +1,197 @@
+using System;
+using System.Collections;
+using System.Text;
+using UnityEngine;
+
+public class MedScanMinigame : Minigame
+{
+ private static readonly string[] ColorNames = new string[]
+ {
+ "Red",
+ "Blue",
+ "Green",
+ "Pink",
+ "Orange",
+ "Yellow",
+ "Black",
+ "White",
+ "Purple",
+ "Brown",
+ "Cyan",
+ "Lime"
+ };
+
+ private static readonly string[] BloodTypes = new string[]
+ {
+ "O-",
+ "A-",
+ "B-",
+ "AB-",
+ "O+",
+ "A+",
+ "B+",
+ "AB+"
+ };
+
+ public TextRenderer text;
+
+ public TextRenderer charStats;
+
+ public HorizontalGauge gauge;
+
+ private MedScanSystem medscan;
+
+ public float ScanDuration = 10f;
+
+ public float ScanTimer;
+
+ private string completeString;
+
+ public AudioClip ScanSound;
+
+ public AudioClip TextSound;
+
+ private Coroutine walking;
+
+ private MedScanMinigame.PositionState state;
+
+ private enum PositionState
+ {
+ None,
+ WalkingToPad,
+ WalkingToOffset
+ }
+
+ public override void Begin(PlayerTask task)
+ {
+ base.Begin(task);
+ this.medscan = (ShipStatus.Instance.Systems[SystemTypes.MedBay] as MedScanSystem);
+ this.gauge.Value = 0f;
+ base.transform.position = new Vector3(100f, 0f, 0f);
+ GameData.PlayerInfo data = PlayerControl.LocalPlayer.Data;
+ int playerId = (int)data.PlayerId;
+ int colorId = (int)data.ColorId;
+ StringBuilder stringBuilder = new StringBuilder();
+ stringBuilder.Append("ID: ");
+ stringBuilder.Append(MedScanMinigame.ColorNames[colorId].Substring(0, 3).ToUpperInvariant());
+ stringBuilder.Append("P" + playerId);
+ stringBuilder.Append(new string(' ', 8));
+ stringBuilder.Append("HT: 3' 6\"");
+ stringBuilder.Append(new string(' ', 8));
+ stringBuilder.Append("WT: 92lb");
+ stringBuilder.AppendLine();
+ stringBuilder.Append("C: ");
+ stringBuilder.Append(MedScanMinigame.ColorNames[colorId].PadRight(17));
+ stringBuilder.Append("BT: ");
+ stringBuilder.Append(MedScanMinigame.BloodTypes[playerId * 3 % MedScanMinigame.BloodTypes.Length]);
+ this.completeString = stringBuilder.ToString();
+ this.charStats.Text = string.Empty;
+ ShipStatus.Instance.RpcRepairSystem(SystemTypes.MedBay, playerId | 128);
+ this.walking = base.StartCoroutine(this.WalkToOffset());
+ }
+
+ private IEnumerator WalkToOffset()
+ {
+ this.state = MedScanMinigame.PositionState.WalkingToOffset;
+ PlayerPhysics myPhysics = PlayerControl.LocalPlayer.MyPhysics;
+ Vector2 vector = ShipStatus.Instance.MedScanner.transform.position;
+ Vector2 a = Vector2.left.Rotate((float)(PlayerControl.LocalPlayer.PlayerId * 36));
+ vector += a / 2f;
+ Camera.main.GetComponent<FollowerCamera>().Locked = false;
+ yield return myPhysics.WalkPlayerTo(vector, 0.001f);
+ yield return new WaitForSeconds(0.1f);
+ Camera.main.GetComponent<FollowerCamera>().Locked = true;
+ this.walking = null;
+ yield break;
+ }
+
+ private IEnumerator WalkToPad()
+ {
+ this.state = MedScanMinigame.PositionState.WalkingToPad;
+ PlayerPhysics myPhysics = PlayerControl.LocalPlayer.MyPhysics;
+ Vector2 worldPos = ShipStatus.Instance.MedScanner.transform.position;
+ worldPos.x += 0.14f;
+ worldPos.y += 0.1f;
+ Camera.main.GetComponent<FollowerCamera>().Locked = false;
+ yield return myPhysics.WalkPlayerTo(worldPos, 0.001f);
+ yield return new WaitForSeconds(0.1f);
+ Camera.main.GetComponent<FollowerCamera>().Locked = true;
+ this.walking = null;
+ yield break;
+ }
+
+ private void FixedUpdate()
+ {
+ if (this.MyNormTask.IsComplete)
+ {
+ return;
+ }
+ byte playerId = PlayerControl.LocalPlayer.PlayerId;
+ if (this.medscan.CurrentUser != playerId)
+ {
+ if (this.medscan.CurrentUser == 255)
+ {
+ this.text.Text = "Scan requested";
+ return;
+ }
+ GameData.PlayerInfo playerById = GameData.Instance.GetPlayerById(this.medscan.CurrentUser);
+ this.text.Text = "Waiting for " + playerById.PlayerName;
+ return;
+ }
+ else
+ {
+ if (this.state != MedScanMinigame.PositionState.WalkingToPad)
+ {
+ if (this.walking != null)
+ {
+ base.StopCoroutine(this.walking);
+ }
+ this.walking = base.StartCoroutine(this.WalkToPad());
+ return;
+ }
+ if (this.walking != null)
+ {
+ return;
+ }
+ if (this.ScanTimer == 0f)
+ {
+ PlayerControl.LocalPlayer.RpcSetScanner(true);
+ SoundManager.Instance.PlaySound(this.ScanSound, false, 1f);
+ }
+ this.ScanTimer += Time.fixedDeltaTime;
+ this.gauge.Value = this.ScanTimer / this.ScanDuration;
+ int num = (int)(Mathf.Min(1f, this.ScanTimer / this.ScanDuration * 1.25f) * (float)this.completeString.Length);
+ if (num > this.charStats.Text.Length)
+ {
+ this.charStats.Text = this.completeString.Substring(0, num);
+ if (this.completeString[num - 1] != ' ')
+ {
+ SoundManager.Instance.PlaySoundImmediate(this.TextSound, false, 0.7f, 0.3f);
+ }
+ }
+ if (this.ScanTimer >= this.ScanDuration)
+ {
+ PlayerControl.LocalPlayer.RpcSetScanner(false);
+ this.text.Text = "Scan complete";
+ this.MyNormTask.NextStep();
+ ShipStatus.Instance.RpcRepairSystem(SystemTypes.MedBay, (int)(playerId | 64));
+ base.StartCoroutine(base.CoStartClose(0.75f));
+ return;
+ }
+ this.text.Text = "Scan complete in: " + (int)(this.ScanDuration - this.ScanTimer);
+ return;
+ }
+ }
+
+ public override void Close()
+ {
+ base.StopAllCoroutines();
+ byte playerId = PlayerControl.LocalPlayer.PlayerId;
+ SoundManager.Instance.StopSound(this.TextSound);
+ SoundManager.Instance.StopSound(this.ScanSound);
+ PlayerControl.LocalPlayer.RpcSetScanner(false);
+ ShipStatus.Instance.RpcRepairSystem(SystemTypes.MedBay, (int)(playerId | 64));
+ Camera.main.GetComponent<FollowerCamera>().Locked = false;
+ base.Close();
+ }
+}
diff --git a/Client/Assembly-CSharp/MedScanSystem.cs b/Client/Assembly-CSharp/MedScanSystem.cs
new file mode 100644
index 0000000..8a5f672
--- /dev/null
+++ b/Client/Assembly-CSharp/MedScanSystem.cs
@@ -0,0 +1,81 @@
+using System;
+using System.Collections.Generic;
+using Hazel;
+using UnityEngine;
+
+public class MedScanSystem : ISystemType
+{
+ public byte CurrentUser { get; private set; } = byte.MaxValue;
+
+ public const byte Request = 128;
+
+ public const byte Release = 64;
+
+ public const byte NumMask = 31;
+
+ public const byte NoPlayer = 255;
+
+ public List<byte> UsersList = new List<byte>();
+
+ public bool Detoriorate(float deltaTime)
+ {
+ if (this.UsersList.Count > 0)
+ {
+ if (this.CurrentUser != this.UsersList[0])
+ {
+ if (this.CurrentUser != 255)
+ {
+ Debug.Log("Released scanner from: " + this.CurrentUser);
+ }
+ this.CurrentUser = this.UsersList[0];
+ Debug.Log("Acquired scanner for: " + this.CurrentUser);
+ return true;
+ }
+ }
+ else if (this.CurrentUser != 255)
+ {
+ Debug.Log("Released scanner from: " + this.CurrentUser);
+ this.CurrentUser = byte.MaxValue;
+ return true;
+ }
+ return false;
+ }
+
+ public void RepairDamage(PlayerControl player, byte data)
+ {
+ byte playerId = data & 31;
+ if ((data & 128) != 0)
+ {
+ if (!this.UsersList.Contains(playerId))
+ {
+ Debug.Log("Added to queue: " + playerId);
+ this.UsersList.Add(playerId);
+ return;
+ }
+ }
+ else if ((data & 64) != 0)
+ {
+ Debug.Log("Removed from queue: " + playerId);
+ this.UsersList.RemoveAll((byte v) => v == playerId);
+ }
+ }
+
+ public void Serialize(MessageWriter writer, bool initialState)
+ {
+ writer.WritePacked(this.UsersList.Count);
+ for (int i = 0; i < this.UsersList.Count; i++)
+ {
+ writer.Write(this.UsersList[i]);
+ }
+ }
+
+ public void Deserialize(MessageReader reader, bool initialState)
+ {
+ this.UsersList.Clear();
+ int num = reader.ReadPackedInt32();
+ for (int i = 0; i < num; i++)
+ {
+ this.UsersList.Add(reader.ReadByte());
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/MeetingHud.cs b/Client/Assembly-CSharp/MeetingHud.cs
new file mode 100644
index 0000000..dbc22cb
--- /dev/null
+++ b/Client/Assembly-CSharp/MeetingHud.cs
@@ -0,0 +1,734 @@
+using System;
+using System.Collections;
+using System.Linq;
+using Assets.CoreScripts;
+using Hazel;
+using InnerNet;
+using UnityEngine;
+
+public class MeetingHud : InnerNetObject, IDisconnectHandler
+{
+ private const float ResultsTime = 5f;
+
+ private const float Depth = -100f;
+
+ public static MeetingHud Instance;
+
+ public Transform ButtonParent;
+
+ public TextRenderer TitleText;
+
+ public Vector3 VoteOrigin = new Vector3(-3.6f, 1.75f);
+
+ public Vector3 VoteButtonOffsets = new Vector2(3.6f, -0.91f);
+
+ private Vector3 CounterOrigin = new Vector2(0.5f, -0.13f);
+
+ private Vector3 CounterOffsets = new Vector2(0.3f, 0f);
+
+ public PlayerVoteArea SkipVoteButton;
+
+ [HideInInspector]
+ private PlayerVoteArea[] playerStates;
+
+ public PlayerVoteArea PlayerButtonPrefab;
+
+ public SpriteRenderer PlayerVotePrefab;
+
+ public Sprite CrackedGlass;
+
+ public SpriteRenderer Glass;
+
+ public PassiveButton ProceedButton;
+
+ public ExileController ExileCutscenePrefab;
+
+ public AudioClip VoteSound;
+
+ public AudioClip VoteLockinSound;
+
+ public AudioClip VoteEndingSound;
+
+ private MeetingHud.VoteStates state;
+
+ public SpriteRenderer SkippedVoting;
+
+ public SpriteRenderer HostIcon;
+
+ public Sprite KillBackground;
+
+ private GameData.PlayerInfo exiledPlayer;
+
+ private bool wasTie;
+
+ public TextRenderer TimerText;
+
+ public float discussionTimer;
+
+ private byte reporterId;
+
+ private bool amDead;
+
+ private float resultsStartedAt;
+
+ private int lastSecond = 10;
+
+ public enum VoteStates
+ {
+ Discussion,
+ NotVoted,
+ Voted,
+ Results,
+ Proceeding
+ }
+
+ private enum RpcCalls
+ {
+ Close,
+ VotingComplete,
+ CastVote,
+ ClearVote
+ }
+
+ private void Awake()
+ {
+ if (!MeetingHud.Instance)
+ {
+ MeetingHud.Instance = this;
+ return;
+ }
+ if (MeetingHud.Instance != this)
+ {
+ UnityEngine.Object.Destroy(base.gameObject);
+ }
+ }
+
+ private void Start()
+ {
+ DestroyableSingleton<HudManager>.Instance.Chat.gameObject.SetActive(true);
+ DestroyableSingleton<HudManager>.Instance.Chat.SetPosition(this);
+ DestroyableSingleton<HudManager>.Instance.StopOxyFlash();
+ DestroyableSingleton<HudManager>.Instance.StopReactorFlash();
+ this.SkipVoteButton.TargetPlayerId = -1;
+ this.SkipVoteButton.Parent = this;
+ Camera.main.GetComponent<FollowerCamera>().Locked = true;
+ if (PlayerControl.LocalPlayer.Data.IsDead)
+ {
+ this.SetForegroundForDead();
+ }
+ AmongUsClient.Instance.DisconnectHandlers.AddUnique(this);
+ }
+
+ private void SetForegroundForDead()
+ {
+ this.amDead = true;
+ this.SkipVoteButton.gameObject.SetActive(false);
+ this.Glass.sprite = this.CrackedGlass;
+ this.Glass.color = Color.white;
+ }
+
+ public void Update()
+ {
+ this.discussionTimer += Time.deltaTime;
+ this.UpdateButtons();
+ switch (this.state)
+ {
+ case MeetingHud.VoteStates.Discussion:
+ {
+ if (this.discussionTimer < (float)PlayerControl.GameOptions.DiscussionTime)
+ {
+ float f = (float)PlayerControl.GameOptions.DiscussionTime - this.discussionTimer;
+ this.TimerText.Text = string.Format("Voting Begins In: {0}s", Mathf.CeilToInt(f));
+ for (int i = 0; i < this.playerStates.Length; i++)
+ {
+ this.playerStates[i].SetDisabled();
+ }
+ this.SkipVoteButton.SetDisabled();
+ return;
+ }
+ this.state = MeetingHud.VoteStates.NotVoted;
+ bool active = PlayerControl.GameOptions.VotingTime > 0;
+ this.TimerText.gameObject.SetActive(active);
+ for (int j = 0; j < this.playerStates.Length; j++)
+ {
+ this.playerStates[j].SetEnabled();
+ }
+ this.SkipVoteButton.SetEnabled();
+ return;
+ }
+ case MeetingHud.VoteStates.NotVoted:
+ case MeetingHud.VoteStates.Voted:
+ if (PlayerControl.GameOptions.VotingTime > 0)
+ {
+ float num = this.discussionTimer - (float)PlayerControl.GameOptions.DiscussionTime;
+ float f2 = Mathf.Max(0f, (float)PlayerControl.GameOptions.VotingTime - num);
+ this.TimerText.Text = string.Format("Voting Ends In: {0}s", Mathf.CeilToInt(f2));
+ if (this.state == MeetingHud.VoteStates.NotVoted && Mathf.CeilToInt(f2) <= this.lastSecond)
+ {
+ this.lastSecond--;
+ base.StartCoroutine(Effects.PulseColor(this.TimerText, Color.red, Color.white, 0.25f));
+ SoundManager.Instance.PlaySound(this.VoteEndingSound, false, 1f).pitch = Mathf.Lerp(1.5f, 0.8f, (float)this.lastSecond / 10f);
+ }
+ if (AmongUsClient.Instance.AmHost && num >= (float)PlayerControl.GameOptions.VotingTime)
+ {
+ this.ForceSkipAll();
+ return;
+ }
+ }
+ break;
+ case MeetingHud.VoteStates.Results:
+ if (AmongUsClient.Instance.GameMode == GameModes.OnlineGame)
+ {
+ float num2 = this.discussionTimer - this.resultsStartedAt;
+ float num3 = Mathf.Max(0f, 5f - num2);
+ this.TimerText.Text = string.Format("Proceeding In: {0}s", Mathf.CeilToInt(num3));
+ if (AmongUsClient.Instance.AmHost && num3 <= 0f)
+ {
+ this.HandleProceed();
+ }
+ }
+ break;
+ default:
+ return;
+ }
+ }
+
+ public IEnumerator CoIntro(PlayerControl reporter, GameData.PlayerInfo targetPlayer)
+ {
+ if (DestroyableSingleton<HudManager>.InstanceExists)
+ {
+ DestroyableSingleton<HudManager>.Instance.Chat.ForceClosed();
+ base.transform.SetParent(DestroyableSingleton<HudManager>.Instance.transform);
+ base.transform.localPosition = new Vector3(0f, -10f, -100f);
+ DestroyableSingleton<HudManager>.Instance.SetHudActive(false);
+ }
+ OverlayKillAnimation killAnimPrefab = (targetPlayer == null) ? DestroyableSingleton<HudManager>.Instance.KillOverlay.EmergencyOverlay : DestroyableSingleton<HudManager>.Instance.KillOverlay.ReportOverlay;
+ DestroyableSingleton<HudManager>.Instance.KillOverlay.ShowOne(killAnimPrefab, reporter, targetPlayer);
+ yield return DestroyableSingleton<HudManager>.Instance.KillOverlay.WaitForFinish();
+ Vector3 temp = new Vector3(0f, 0f, -50f);
+ for (float timer = 0f; timer < 0.25f; timer += Time.deltaTime)
+ {
+ float t = timer / 0.25f;
+ temp.y = Mathf.SmoothStep(-10f, 0f, t);
+ base.transform.localPosition = temp;
+ yield return null;
+ }
+ temp.y = 0f;
+ base.transform.localPosition = temp;
+ this.TitleText.Text = "Who Is The Impostor?";
+ if (!PlayerControl.LocalPlayer.Data.IsDead)
+ {
+ yield return DestroyableSingleton<HudManager>.Instance.ShowEmblem(false);
+ }
+ for (int i = 0; i < this.playerStates.Length; i++)
+ {
+ base.StartCoroutine(this.playerStates[i].CoAnimateOverlay());
+ }
+ yield break;
+ }
+
+ private IEnumerator CoStartCutscene()
+ {
+ yield return DestroyableSingleton<HudManager>.Instance.CoFadeFullScreen(Color.clear, Color.black, 1f);
+ ExileController exileController = UnityEngine.Object.Instantiate<ExileController>(this.ExileCutscenePrefab);
+ exileController.transform.SetParent(DestroyableSingleton<HudManager>.Instance.transform, false);
+ exileController.transform.localPosition = new Vector3(0f, 0f, -60f);
+ exileController.Begin(this.exiledPlayer, this.wasTie);
+ this.DespawnOnDestroy = false;
+ UnityEngine.Object.Destroy(base.gameObject);
+ yield break;
+ }
+
+ public void ServerStart(byte reporter)
+ {
+ this.reporterId = reporter;
+ this.PopulateButtons(reporter);
+ }
+
+ public void Close()
+ {
+ GameData.PlayerInfo data = PlayerControl.LocalPlayer.Data;
+ DestroyableSingleton<HudManager>.Instance.Chat.SetPosition(null);
+ DestroyableSingleton<HudManager>.Instance.Chat.SetVisible(data.IsDead);
+ base.StartCoroutine(this.CoStartCutscene());
+ }
+
+ private void VotingComplete(byte[] states, GameData.PlayerInfo exiled, bool tie)
+ {
+ if (this.state == MeetingHud.VoteStates.Results)
+ {
+ return;
+ }
+ this.state = MeetingHud.VoteStates.Results;
+ this.resultsStartedAt = this.discussionTimer;
+ this.exiledPlayer = exiled;
+ this.wasTie = tie;
+ this.SkipVoteButton.gameObject.SetActive(false);
+ this.SkippedVoting.gameObject.SetActive(true);
+ AmongUsClient.Instance.DisconnectHandlers.Remove(this);
+ this.PopulateResults(states);
+ this.SetupProceedButton();
+ }
+
+ public bool Select(int suspectStateIdx)
+ {
+ if (this.discussionTimer < (float)PlayerControl.GameOptions.DiscussionTime)
+ {
+ return false;
+ }
+ if (PlayerControl.LocalPlayer.Data.IsDead)
+ {
+ return false;
+ }
+ SoundManager.Instance.PlaySound(this.VoteSound, false, 1f).volume = 0.8f;
+ for (int i = 0; i < this.playerStates.Length; i++)
+ {
+ PlayerVoteArea playerVoteArea = this.playerStates[i];
+ if (suspectStateIdx != (int)playerVoteArea.TargetPlayerId)
+ {
+ playerVoteArea.ClearButtons();
+ }
+ }
+ if (suspectStateIdx != -1)
+ {
+ this.SkipVoteButton.ClearButtons();
+ }
+ return true;
+ }
+
+ public void Confirm(sbyte suspectStateIdx)
+ {
+ if (PlayerControl.LocalPlayer.Data.IsDead)
+ {
+ return;
+ }
+ for (int i = 0; i < this.playerStates.Length; i++)
+ {
+ PlayerVoteArea playerVoteArea = this.playerStates[i];
+ playerVoteArea.ClearButtons();
+ playerVoteArea.voteComplete = true;
+ }
+ this.SkipVoteButton.ClearButtons();
+ this.SkipVoteButton.voteComplete = true;
+ this.SkipVoteButton.gameObject.SetActive(false);
+ MeetingHud.VoteStates voteStates = this.state;
+ if (voteStates != MeetingHud.VoteStates.NotVoted)
+ {
+ return;
+ }
+ this.state = MeetingHud.VoteStates.Voted;
+ this.CmdCastVote(PlayerControl.LocalPlayer.PlayerId, suspectStateIdx);
+ }
+
+ public void HandleDisconnect(PlayerControl pc, DisconnectReasons reason)
+ {
+ if (!AmongUsClient.Instance.AmHost)
+ {
+ return;
+ }
+ int num = this.playerStates.IndexOf((PlayerVoteArea pv) => pv.TargetPlayerId == (sbyte)pc.PlayerId);
+ PlayerVoteArea playerVoteArea = this.playerStates[num];
+ playerVoteArea.isDead = true;
+ playerVoteArea.Overlay.gameObject.SetActive(true);
+ for (int i = 0; i < this.playerStates.Length; i++)
+ {
+ PlayerVoteArea playerVoteArea2 = this.playerStates[i];
+ if (!playerVoteArea2.isDead && playerVoteArea2.didVote && playerVoteArea2.votedFor == (sbyte)pc.PlayerId)
+ {
+ playerVoteArea2.UnsetVote();
+ base.SetDirtyBit(1U << i);
+ GameData.PlayerInfo playerById = GameData.Instance.GetPlayerById((byte)playerVoteArea2.TargetPlayerId);
+ if (playerById != null)
+ {
+ int clientIdFromCharacter = AmongUsClient.Instance.GetClientIdFromCharacter(playerById.Object);
+ if (clientIdFromCharacter != -1)
+ {
+ this.RpcClearVote(clientIdFromCharacter);
+ }
+ }
+ }
+ }
+ base.SetDirtyBit(1U << num);
+ this.CheckForEndVoting();
+ if (this.state == MeetingHud.VoteStates.Results)
+ {
+ this.SetupProceedButton();
+ }
+ }
+
+ public void HandleDisconnect()
+ {
+ }
+
+ private void ForceSkipAll()
+ {
+ for (int i = 0; i < this.playerStates.Length; i++)
+ {
+ PlayerVoteArea playerVoteArea = this.playerStates[i];
+ if (!playerVoteArea.didVote)
+ {
+ playerVoteArea.didVote = true;
+ playerVoteArea.votedFor = -2;
+ base.SetDirtyBit(1U << i);
+ }
+ }
+ this.CheckForEndVoting();
+ }
+
+ public void CastVote(byte srcPlayerId, sbyte suspectPlayerId)
+ {
+ int num = this.playerStates.IndexOf((PlayerVoteArea pv) => pv.TargetPlayerId == (sbyte)srcPlayerId);
+ PlayerVoteArea playerVoteArea = this.playerStates[num];
+ if (!playerVoteArea.isDead && !playerVoteArea.didVote)
+ {
+ if (PlayerControl.LocalPlayer.PlayerId == srcPlayerId || AmongUsClient.Instance.GameMode != GameModes.LocalGame)
+ {
+ SoundManager.Instance.PlaySound(this.VoteLockinSound, false, 1f);
+ }
+ playerVoteArea.SetVote(suspectPlayerId);
+ base.SetDirtyBit(1U << num);
+ this.CheckForEndVoting();
+ PlayerControl.LocalPlayer.RpcSendChatNote(srcPlayerId, ChatNoteTypes.DidVote);
+ }
+ }
+
+ public void ClearVote()
+ {
+ for (int i = 0; i < this.playerStates.Length; i++)
+ {
+ this.playerStates[i].voteComplete = false;
+ }
+ this.SkipVoteButton.voteComplete = false;
+ this.SkipVoteButton.gameObject.SetActive(true);
+ this.state = MeetingHud.VoteStates.NotVoted;
+ }
+
+ private void CheckForEndVoting()
+ {
+ if (this.playerStates.All((PlayerVoteArea ps) => ps.isDead || ps.didVote))
+ {
+ byte[] self = this.CalculateVotes();
+ bool tie;
+ int maxIdx = self.IndexOfMax((byte p) => (int)p, out tie) - 1;
+ GameData.PlayerInfo exiled = GameData.Instance.AllPlayers.FirstOrDefault((GameData.PlayerInfo v) => (int)v.PlayerId == maxIdx);
+ byte[] states = (from ps in this.playerStates
+ select ps.GetState()).ToArray<byte>();
+ this.RpcVotingComplete(states, exiled, tie);
+ }
+ }
+
+ private byte[] CalculateVotes()
+ {
+ byte[] array = new byte[11];
+ for (int i = 0; i < this.playerStates.Length; i++)
+ {
+ PlayerVoteArea playerVoteArea = this.playerStates[i];
+ if (playerVoteArea.didVote)
+ {
+ int num = (int)(playerVoteArea.votedFor + 1);
+ if (num >= 0 && num < array.Length)
+ {
+ byte[] array2 = array;
+ int num2 = num;
+ array2[num2] += 1;
+ }
+ }
+ }
+ return array;
+ }
+
+ public override bool Serialize(MessageWriter writer, bool initialState)
+ {
+ if (this.playerStates == null)
+ {
+ return false;
+ }
+ if (initialState)
+ {
+ for (int i = 0; i < this.playerStates.Length; i++)
+ {
+ this.playerStates[i].Serialize(writer);
+ }
+ }
+ else
+ {
+ writer.WritePacked(this.DirtyBits);
+ for (int j = 0; j < this.playerStates.Length; j++)
+ {
+ if ((this.DirtyBits & 1U << j) != 0U)
+ {
+ this.playerStates[j].Serialize(writer);
+ }
+ }
+ }
+ this.DirtyBits = 0U;
+ return true;
+ }
+
+ public override void Deserialize(MessageReader reader, bool initialState)
+ {
+ if (initialState)
+ {
+ MeetingHud.Instance = this;
+ this.PopulateButtons(0);
+ for (int i = 0; i < this.playerStates.Length; i++)
+ {
+ PlayerVoteArea playerVoteArea = this.playerStates[i];
+ playerVoteArea.Deserialize(reader);
+ if (playerVoteArea.didReport)
+ {
+ this.reporterId = (byte)playerVoteArea.TargetPlayerId;
+ }
+ }
+ return;
+ }
+ uint num = reader.ReadPackedUInt32();
+ for (int j = 0; j < this.playerStates.Length; j++)
+ {
+ if ((num & 1U << j) != 0U)
+ {
+ this.playerStates[j].Deserialize(reader);
+ }
+ }
+ }
+
+ public void HandleProceed()
+ {
+ if (!AmongUsClient.Instance.AmHost)
+ {
+ base.StartCoroutine(Effects.Shake(this.HostIcon.transform, 0.75f, 0.25f));
+ return;
+ }
+ if (this.state != MeetingHud.VoteStates.Results)
+ {
+ return;
+ }
+ this.state = MeetingHud.VoteStates.Proceeding;
+ this.RpcClose();
+ }
+
+ private void SetupProceedButton()
+ {
+ if (AmongUsClient.Instance.GameMode != GameModes.OnlineGame)
+ {
+ this.TimerText.gameObject.SetActive(false);
+ this.ProceedButton.gameObject.SetActive(true);
+ this.HostIcon.gameObject.SetActive(true);
+ GameData.PlayerInfo host = GameData.Instance.GetHost();
+ if (host != null)
+ {
+ PlayerControl.SetPlayerMaterialColors((int)host.ColorId, this.HostIcon);
+ return;
+ }
+ this.HostIcon.enabled = false;
+ }
+ }
+
+ private void PopulateResults(byte[] states)
+ {
+ DestroyableSingleton<Telemetry>.Instance.WriteMeetingEnded(states, this.discussionTimer);
+ this.TitleText.Text = "Voting Results";
+ int num = 0;
+ for (int i = 0; i < this.playerStates.Length; i++)
+ {
+ PlayerVoteArea playerVoteArea = this.playerStates[i];
+ playerVoteArea.ClearForResults();
+ int num2 = 0;
+ for (int j = 0; j < this.playerStates.Length; j++)
+ {
+ if (!states[j].HasAnyBit(128))
+ {
+ GameData.PlayerInfo playerById = GameData.Instance.GetPlayerById((byte)this.playerStates[j].TargetPlayerId);
+ int num3 = (int)((states[j] & 15) - 1);
+ if (num3 == (int)playerVoteArea.TargetPlayerId)
+ {
+ SpriteRenderer spriteRenderer = UnityEngine.Object.Instantiate<SpriteRenderer>(this.PlayerVotePrefab);
+ PlayerControl.SetPlayerMaterialColors((int)playerById.ColorId, spriteRenderer);
+ spriteRenderer.transform.SetParent(playerVoteArea.transform);
+ spriteRenderer.transform.localPosition = this.CounterOrigin + new Vector3(this.CounterOffsets.x * (float)num2, 0f, 0f);
+ spriteRenderer.transform.localScale = Vector3.zero;
+ base.StartCoroutine(Effects.Bloop((float)num2 * 0.5f, spriteRenderer.transform, 0.5f));
+ num2++;
+ }
+ else if (i == 0 && num3 == -1)
+ {
+ SpriteRenderer spriteRenderer2 = UnityEngine.Object.Instantiate<SpriteRenderer>(this.PlayerVotePrefab);
+ PlayerControl.SetPlayerMaterialColors((int)playerById.ColorId, spriteRenderer2);
+ spriteRenderer2.transform.SetParent(this.SkippedVoting.transform);
+ spriteRenderer2.transform.localPosition = this.CounterOrigin + new Vector3(this.CounterOffsets.x * (float)num, 0f, 0f);
+ spriteRenderer2.transform.localScale = Vector3.zero;
+ base.StartCoroutine(Effects.Bloop((float)num * 0.5f, spriteRenderer2.transform, 0.5f));
+ num++;
+ }
+ }
+ }
+ }
+ }
+
+ private void UpdateButtons()
+ {
+ if (PlayerControl.LocalPlayer.Data.IsDead && !this.amDead)
+ {
+ this.SetForegroundForDead();
+ }
+ if (AmongUsClient.Instance.AmHost)
+ {
+ for (int i = 0; i < this.playerStates.Length; i++)
+ {
+ PlayerVoteArea playerVoteArea = this.playerStates[i];
+ GameData.PlayerInfo playerById = GameData.Instance.GetPlayerById((byte)playerVoteArea.TargetPlayerId);
+ if (playerById == null)
+ {
+ playerVoteArea.SetDisabled();
+ }
+ else
+ {
+ bool flag = playerById.Disconnected || playerById.IsDead;
+ if (flag != playerVoteArea.isDead)
+ {
+ playerVoteArea.SetDead(playerById.PlayerId == PlayerControl.LocalPlayer.PlayerId, this.reporterId == playerById.PlayerId, flag);
+ base.SetDirtyBit(1U << i);
+ }
+ }
+ }
+ }
+ }
+
+ private void PopulateButtons(byte reporter)
+ {
+ this.playerStates = new PlayerVoteArea[GameData.Instance.PlayerCount];
+ for (int i = 0; i < this.playerStates.Length; i++)
+ {
+ GameData.PlayerInfo playerInfo = GameData.Instance.AllPlayers[i];
+ PlayerVoteArea playerVoteArea = this.playerStates[i] = this.CreateButton(playerInfo);
+ playerVoteArea.Parent = this;
+ playerVoteArea.TargetPlayerId = (sbyte)playerInfo.PlayerId;
+ playerVoteArea.SetDead(playerInfo.PlayerId == PlayerControl.LocalPlayer.PlayerId, reporter == playerInfo.PlayerId, playerInfo.Disconnected || playerInfo.IsDead);
+ }
+ this.SortButtons();
+ }
+
+ private void SortButtons()
+ {
+ PlayerVoteArea[] array = this.playerStates.OrderBy(delegate(PlayerVoteArea p)
+ {
+ if (!p.isDead)
+ {
+ return 0;
+ }
+ return 50;
+ }).ThenBy((PlayerVoteArea p) => p.TargetPlayerId).ToArray<PlayerVoteArea>();
+ for (int i = 0; i < array.Length; i++)
+ {
+ int num = i % 2;
+ int num2 = i / 2;
+ array[i].transform.localPosition = this.VoteOrigin + new Vector3(this.VoteButtonOffsets.x * (float)num, this.VoteButtonOffsets.y * (float)num2, -1f);
+ }
+ }
+
+ private PlayerVoteArea CreateButton(GameData.PlayerInfo playerInfo)
+ {
+ PlayerVoteArea playerVoteArea = UnityEngine.Object.Instantiate<PlayerVoteArea>(this.PlayerButtonPrefab, this.ButtonParent.transform);
+ PlayerControl.SetPlayerMaterialColors((int)playerInfo.ColorId, playerVoteArea.PlayerIcon);
+ playerVoteArea.NameText.Text = playerInfo.PlayerName;
+ bool flag = PlayerControl.LocalPlayer.Data.IsImpostor && playerInfo.IsImpostor;
+ playerVoteArea.NameText.Color = (flag ? Palette.ImpostorRed : Color.white);
+ playerVoteArea.transform.localScale = Vector3.one;
+ return playerVoteArea;
+ }
+
+ public bool DidVote(byte playerId)
+ {
+ return this.playerStates.First((PlayerVoteArea p) => p.TargetPlayerId == (sbyte)playerId).didVote;
+ }
+
+ public int GetVotesRemaining()
+ {
+ int result;
+ try
+ {
+ result = this.playerStates.Count((PlayerVoteArea ps) => !ps.isDead && !ps.didVote);
+ }
+ catch
+ {
+ result = 0;
+ }
+ return result;
+ }
+
+ public void RpcClose()
+ {
+ if (AmongUsClient.Instance.AmClient)
+ {
+ this.Close();
+ }
+ AmongUsClient.Instance.SendRpc(this.NetId, 0, SendOption.Reliable);
+ }
+
+ public void CmdCastVote(byte playerId, sbyte suspectIdx)
+ {
+ if (AmongUsClient.Instance.AmHost)
+ {
+ this.CastVote(playerId, suspectIdx);
+ return;
+ }
+ MessageWriter messageWriter = AmongUsClient.Instance.StartRpcImmediately(this.NetId, 2, SendOption.Reliable, AmongUsClient.Instance.HostId);
+ messageWriter.Write(playerId);
+ messageWriter.Write(suspectIdx);
+ AmongUsClient.Instance.FinishRpcImmediately(messageWriter);
+ }
+
+ private void RpcVotingComplete(byte[] states, GameData.PlayerInfo exiled, bool tie)
+ {
+ if (AmongUsClient.Instance.AmClient)
+ {
+ this.VotingComplete(states, exiled, tie);
+ }
+ MessageWriter messageWriter = AmongUsClient.Instance.StartRpc(this.NetId, 1, SendOption.Reliable);
+ messageWriter.WriteBytesAndSize(states);
+ messageWriter.Write((exiled != null) ? exiled.PlayerId : byte.MaxValue);
+ messageWriter.Write(tie);
+ messageWriter.EndMessage();
+ }
+
+ private void RpcClearVote(int clientId)
+ {
+ if (AmongUsClient.Instance.ClientId == clientId)
+ {
+ this.ClearVote();
+ return;
+ }
+ MessageWriter msg = AmongUsClient.Instance.StartRpcImmediately(this.NetId, 3, SendOption.Reliable, clientId);
+ AmongUsClient.Instance.FinishRpcImmediately(msg);
+ }
+
+ public override void HandleRpc(byte callId, MessageReader reader)
+ {
+ switch (callId)
+ {
+ case 0:
+ this.Close();
+ return;
+ case 1:
+ {
+ byte[] states = reader.ReadBytesAndSize();
+ GameData.PlayerInfo playerById = GameData.Instance.GetPlayerById(reader.ReadByte());
+ bool tie = reader.ReadBoolean();
+ this.VotingComplete(states, playerById, tie);
+ return;
+ }
+ case 2:
+ {
+ byte srcPlayerId = reader.ReadByte();
+ sbyte suspectPlayerId = reader.ReadSByte();
+ this.CastVote(srcPlayerId, suspectPlayerId);
+ return;
+ }
+ case 3:
+ this.ClearVote();
+ return;
+ default:
+ return;
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/MeetingRoomManager.cs b/Client/Assembly-CSharp/MeetingRoomManager.cs
new file mode 100644
index 0000000..dcb519f
--- /dev/null
+++ b/Client/Assembly-CSharp/MeetingRoomManager.cs
@@ -0,0 +1,36 @@
+using System;
+using InnerNet;
+
+public class MeetingRoomManager : IDisconnectHandler
+{
+ public static readonly MeetingRoomManager Instance = new MeetingRoomManager();
+
+ private PlayerControl reporter;
+
+ private GameData.PlayerInfo target;
+
+ public void AssignSelf(PlayerControl reporter, GameData.PlayerInfo target)
+ {
+ this.reporter = reporter;
+ this.target = target;
+ AmongUsClient.Instance.DisconnectHandlers.AddUnique(this);
+ }
+
+ public void RemoveSelf()
+ {
+ AmongUsClient.Instance.DisconnectHandlers.Remove(this);
+ }
+
+ public void HandleDisconnect(PlayerControl pc, DisconnectReasons reason)
+ {
+ if (AmongUsClient.Instance.AmHost)
+ {
+ this.reporter.CmdReportDeadBody(this.target);
+ }
+ }
+
+ public void HandleDisconnect()
+ {
+ this.HandleDisconnect(null, DisconnectReasons.ExitGame);
+ }
+}
diff --git a/Client/Assembly-CSharp/MemSafeStringExtensions.cs b/Client/Assembly-CSharp/MemSafeStringExtensions.cs
new file mode 100644
index 0000000..034b2bc
--- /dev/null
+++ b/Client/Assembly-CSharp/MemSafeStringExtensions.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+
+public static class MemSafeStringExtensions
+{
+ public static void SafeSplit(this SubString subString, List<SubString> output, char delim)
+ {
+ subString.Source.SafeSplit(output, delim, subString.Start, subString.Length);
+ }
+
+ public static void SafeSplit(this string source, List<SubString> output, char delim)
+ {
+ source.SafeSplit(output, delim, 0, source.Length);
+ }
+
+ public static void SafeSplit(this string source, List<SubString> output, char delim, int start, int length)
+ {
+ output.Clear();
+ int num = start;
+ int num2 = start + length;
+ for (int i = start; i < num2; i++)
+ {
+ if (source[i] == delim)
+ {
+ if (num != i)
+ {
+ output.Add(new SubString(source, num, i - num));
+ }
+ num = i + 1;
+ }
+ }
+ if (num != num2)
+ {
+ output.Add(new SubString(source, num, num2 - num));
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/MeshRendererExtensions.cs b/Client/Assembly-CSharp/MeshRendererExtensions.cs
new file mode 100644
index 0000000..dddc50d
--- /dev/null
+++ b/Client/Assembly-CSharp/MeshRendererExtensions.cs
@@ -0,0 +1,23 @@
+using System;
+using UnityEngine;
+
+public static class MeshRendererExtensions
+{
+ public static void SetSprite(this MeshRenderer self, Texture2D spr)
+ {
+ if (spr != null)
+ {
+ self.SetCutout(spr);
+ self.material.color = Color.white;
+ return;
+ }
+ self.SetCutout(null);
+ self.material.color = Color.clear;
+ }
+
+ public static void SetCutout(this MeshRenderer self, Texture2D txt)
+ {
+ self.material.SetTexture("_MainTex", txt);
+ self.material.SetTexture("_EmissionMap", txt);
+ }
+}
diff --git a/Client/Assembly-CSharp/Minigame.cs b/Client/Assembly-CSharp/Minigame.cs
new file mode 100644
index 0000000..0897e13
--- /dev/null
+++ b/Client/Assembly-CSharp/Minigame.cs
@@ -0,0 +1,166 @@
+using System;
+using System.Collections;
+using UnityEngine;
+
+public abstract class Minigame : MonoBehaviour
+{
+ public global::Console Console { get; set; }
+
+ protected int ConsoleId
+ {
+ get
+ {
+ if (!this.Console)
+ {
+ return 0;
+ }
+ return this.Console.ConsoleId;
+ }
+ }
+
+ public static Minigame Instance;
+
+ public const float Depth = -50f;
+
+ public TransitionType TransType;
+
+ protected PlayerTask MyTask;
+
+ protected NormalPlayerTask MyNormTask;
+
+ protected Minigame.CloseState amClosing;
+
+ public AudioClip OpenSound;
+
+ public AudioClip CloseSound;
+
+ protected enum CloseState
+ {
+ None,
+ Waiting,
+ Closing
+ }
+
+ public virtual void Begin(PlayerTask task)
+ {
+ Minigame.Instance = this;
+ this.MyTask = task;
+ this.MyNormTask = (task as NormalPlayerTask);
+ if (PlayerControl.LocalPlayer)
+ {
+ if (MapBehaviour.Instance)
+ {
+ MapBehaviour.Instance.Close();
+ }
+ PlayerControl.LocalPlayer.NetTransform.Halt();
+ }
+ base.StartCoroutine(this.CoAnimateOpen());
+ }
+
+ protected IEnumerator CoStartClose(float duration = 0.75f)
+ {
+ if (this.amClosing != Minigame.CloseState.None)
+ {
+ yield break;
+ }
+ this.amClosing = Minigame.CloseState.Waiting;
+ yield return Effects.Wait(duration);
+ this.Close();
+ yield break;
+ }
+
+ [Obsolete("Don't use, I just don't want to reselect the close button event handlers", true)]
+ public void Close(bool allowMovement)
+ {
+ this.Close();
+ }
+
+ public virtual void Close()
+ {
+ if (this.amClosing != Minigame.CloseState.Closing)
+ {
+ if (this.CloseSound && Constants.ShouldPlaySfx())
+ {
+ SoundManager.Instance.PlaySound(this.CloseSound, false, 1f);
+ }
+ this.amClosing = Minigame.CloseState.Closing;
+ base.StartCoroutine(this.CoDestroySelf());
+ return;
+ }
+ UnityEngine.Object.Destroy(base.gameObject);
+ }
+
+ protected virtual IEnumerator CoAnimateOpen()
+ {
+ if (this.OpenSound && Constants.ShouldPlaySfx())
+ {
+ SoundManager.Instance.PlaySound(this.OpenSound, false, 1f);
+ }
+ TransitionType transType = this.TransType;
+ if (transType != TransitionType.SlideBottom)
+ {
+ if (transType == TransitionType.Alpha)
+ {
+ SpriteRenderer[] rends = base.GetComponentsInChildren<SpriteRenderer>();
+ for (float timer = 0f; timer < 0.25f; timer += Time.deltaTime)
+ {
+ float t = timer / 0.25f;
+ for (int i = 0; i < rends.Length; i++)
+ {
+ rends[i].color = Color.Lerp(Palette.ClearWhite, Color.white, t);
+ }
+ yield return null;
+ }
+ for (int j = 0; j < rends.Length; j++)
+ {
+ rends[j].color = Color.white;
+ }
+ rends = null;
+ }
+ }
+ else
+ {
+ for (float timer = 0f; timer < 0.25f; timer += Time.deltaTime)
+ {
+ float t2 = timer / 0.25f;
+ base.transform.localPosition = new Vector3(0f, Mathf.SmoothStep(-8f, 0f, t2), -50f);
+ yield return null;
+ }
+ base.transform.localPosition = new Vector3(0f, 0f, -50f);
+ }
+ yield break;
+ }
+
+ protected virtual IEnumerator CoDestroySelf()
+ {
+ TransitionType transType = this.TransType;
+ if (transType != TransitionType.SlideBottom)
+ {
+ if (transType == TransitionType.Alpha)
+ {
+ SpriteRenderer[] rends = base.GetComponentsInChildren<SpriteRenderer>();
+ for (float timer = 0f; timer < 0.25f; timer += Time.deltaTime)
+ {
+ float t = timer / 0.25f;
+ for (int i = 0; i < rends.Length; i++)
+ {
+ rends[i].color = Color.Lerp(Color.white, Palette.ClearWhite, t);
+ }
+ yield return null;
+ }
+ rends = null;
+ }
+ }
+ else
+ {
+ for (float timer = 0f; timer < 0.25f; timer += Time.deltaTime)
+ {
+ float t2 = timer / 0.25f;
+ base.transform.localPosition = new Vector3(0f, Mathf.SmoothStep(0f, -8f, t2), -50f);
+ yield return null;
+ }
+ }
+ UnityEngine.Object.Destroy(base.gameObject);
+ yield break;
+ }
+}
diff --git a/Client/Assembly-CSharp/MonoPInvokeCallbackAttribute.cs b/Client/Assembly-CSharp/MonoPInvokeCallbackAttribute.cs
new file mode 100644
index 0000000..96960fe
--- /dev/null
+++ b/Client/Assembly-CSharp/MonoPInvokeCallbackAttribute.cs
@@ -0,0 +1,8 @@
+using System;
+
+public sealed class MonoPInvokeCallbackAttribute : Attribute
+{
+ public MonoPInvokeCallbackAttribute(Type type)
+ {
+ }
+}
diff --git a/Client/Assembly-CSharp/NameTextBehaviour.cs b/Client/Assembly-CSharp/NameTextBehaviour.cs
new file mode 100644
index 0000000..83a3ad7
--- /dev/null
+++ b/Client/Assembly-CSharp/NameTextBehaviour.cs
@@ -0,0 +1,61 @@
+using System;
+using UnityEngine;
+using UnityEngine.Events;
+
+public class NameTextBehaviour : MonoBehaviour
+{
+ public static NameTextBehaviour Instance;
+
+ public TextBox nameSource;
+
+ public void Start()
+ {
+ NameTextBehaviour.Instance = this;
+ this.nameSource.SetText(SaveManager.PlayerName, "");
+ this.nameSource.OnFocusLost.AddListener(new UnityAction(this.UpdateName));
+ }
+
+ public void UpdateName()
+ {
+ if (this.ShakeIfInvalid())
+ {
+ return;
+ }
+ SaveManager.PlayerName = this.nameSource.text;
+ }
+
+ public static bool IsValidName(string text)
+ {
+ if (text == null || text.Length == 0)
+ {
+ return false;
+ }
+ if (text.Equals("Enter Name", StringComparison.OrdinalIgnoreCase))
+ {
+ return false;
+ }
+ if (BlockedWords.ContainsWord(text))
+ {
+ return false;
+ }
+ bool result = false;
+ for (int i = 0; i < text.Length; i++)
+ {
+ if (text[i] != ' ')
+ {
+ result = true;
+ }
+ }
+ return result;
+ }
+
+ public bool ShakeIfInvalid()
+ {
+ if (!NameTextBehaviour.IsValidName(this.nameSource.text))
+ {
+ base.StartCoroutine(Effects.Shake(this.nameSource.transform, 0.75f, 0.25f));
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/Client/Assembly-CSharp/NavigationMinigame.cs b/Client/Assembly-CSharp/NavigationMinigame.cs
new file mode 100644
index 0000000..6e789e2
--- /dev/null
+++ b/Client/Assembly-CSharp/NavigationMinigame.cs
@@ -0,0 +1,88 @@
+using System;
+using System.Collections;
+using UnityEngine;
+
+public class NavigationMinigame : Minigame
+{
+ public MeshRenderer TwoAxisImage;
+
+ public SpriteRenderer CrossHairImage;
+
+ public Collider2D hitbox;
+
+ private Controller myController = new Controller();
+
+ private Vector2 crossHair;
+
+ private Vector2 half = new Vector2(0.5f, 0.5f);
+
+ public override void Begin(PlayerTask task)
+ {
+ base.Begin(task);
+ this.crossHair = UnityEngine.Random.insideUnitCircle.normalized / 2f * 0.6f;
+ Vector3 localPosition = new Vector3(this.crossHair.x * this.TwoAxisImage.bounds.size.x, this.crossHair.y * this.TwoAxisImage.bounds.size.y, -2f);
+ this.CrossHairImage.transform.localPosition = localPosition;
+ this.TwoAxisImage.material.SetVector("_CrossHair", this.crossHair + this.half);
+ }
+
+ public void FixedUpdate()
+ {
+ if (this.MyNormTask && this.MyNormTask.IsComplete)
+ {
+ return;
+ }
+ this.myController.Update();
+ DragState dragState = this.myController.CheckDrag(this.hitbox, false);
+ if (dragState != DragState.Dragging)
+ {
+ if (dragState != DragState.Released)
+ {
+ return;
+ }
+ if ((this.crossHair - this.half).magnitude < 0.05f)
+ {
+ base.StartCoroutine(this.CompleteGame());
+ this.MyNormTask.NextStep();
+ }
+ }
+ else
+ {
+ Vector2 dragPosition = this.myController.DragPosition;
+ Vector2 a = dragPosition - (this.TwoAxisImage.transform.position - this.TwoAxisImage.bounds.size / 2f);
+ this.crossHair = a.Div(this.TwoAxisImage.bounds.size);
+ if ((this.crossHair - this.half).magnitude < 0.45f)
+ {
+ Vector3 localPosition = dragPosition - base.transform.position;
+ localPosition.z = -2f;
+ this.CrossHairImage.transform.localPosition = localPosition;
+ this.TwoAxisImage.material.SetVector("_CrossHair", this.crossHair);
+ return;
+ }
+ }
+ }
+
+ private IEnumerator CompleteGame()
+ {
+ WaitForSeconds wait = new WaitForSeconds(0.1f);
+ Color green = new Color(0f, 0.8f, 0f, 1f);
+ Color32 yellow = new Color32(byte.MaxValue, 202, 0, byte.MaxValue);
+ this.CrossHairImage.transform.localPosition = new Vector3(0f, 0f, -2f);
+ this.TwoAxisImage.material.SetVector("_CrossHair", this.half);
+ this.CrossHairImage.color = yellow;
+ this.TwoAxisImage.material.SetColor("_CrossColor", yellow);
+ yield return wait;
+ this.CrossHairImage.color = Color.white;
+ this.TwoAxisImage.material.SetColor("_CrossColor", Color.white);
+ yield return wait;
+ this.CrossHairImage.color = yellow;
+ this.TwoAxisImage.material.SetColor("_CrossColor", yellow);
+ yield return wait;
+ this.CrossHairImage.color = Color.white;
+ this.TwoAxisImage.material.SetColor("_CrossColor", Color.white);
+ yield return wait;
+ this.CrossHairImage.color = green;
+ this.TwoAxisImage.material.SetColor("_CrossColor", green);
+ yield return base.CoStartClose(0.75f);
+ yield break;
+ }
+}
diff --git a/Client/Assembly-CSharp/NoOxyTask.cs b/Client/Assembly-CSharp/NoOxyTask.cs
new file mode 100644
index 0000000..47f9e88
--- /dev/null
+++ b/Client/Assembly-CSharp/NoOxyTask.cs
@@ -0,0 +1,106 @@
+using System;
+using System.Linq;
+using System.Text;
+using UnityEngine;
+
+public class NoOxyTask : SabotageTask
+{
+ public override int TaskStep
+ {
+ get
+ {
+ return this.reactor.UserCount;
+ }
+ }
+
+ public override bool IsComplete
+ {
+ get
+ {
+ return this.isComplete;
+ }
+ }
+
+ private bool isComplete;
+
+ private LifeSuppSystemType reactor;
+
+ private bool even;
+
+ public int targetNumber;
+
+ public override void Initialize()
+ {
+ this.targetNumber = IntRange.Next(0, 99999);
+ ShipStatus instance = ShipStatus.Instance;
+ this.reactor = (LifeSuppSystemType)instance.Systems[SystemTypes.LifeSupp];
+ DestroyableSingleton<HudManager>.Instance.StartOxyFlash();
+ base.SetupArrows();
+ }
+
+ private void FixedUpdate()
+ {
+ if (this.isComplete)
+ {
+ return;
+ }
+ if (!this.reactor.IsActive)
+ {
+ this.Complete();
+ return;
+ }
+ for (int i = 0; i < this.Arrows.Length; i++)
+ {
+ this.Arrows[i].gameObject.SetActive(!this.reactor.GetConsoleComplete(i));
+ }
+ }
+
+ public override bool ValidConsole(global::Console console)
+ {
+ return !this.reactor.GetConsoleComplete(console.ConsoleId) && console.TaskTypes.Contains(TaskTypes.RestoreOxy);
+ }
+
+ public override void OnRemove()
+ {
+ }
+
+ public override void Complete()
+ {
+ this.isComplete = true;
+ PlayerControl.LocalPlayer.RemoveTask(this);
+ if (this.didContribute)
+ {
+ StatsManager instance = StatsManager.Instance;
+ uint sabsFixed = instance.SabsFixed;
+ instance.SabsFixed = sabsFixed + 1U;
+ }
+ }
+
+ public override void AppendTaskText(StringBuilder sb)
+ {
+ this.even = !this.even;
+ Color color = this.even ? Color.yellow : Color.red;
+ if (this.reactor != null)
+ {
+ sb.Append(color.ToTextColor());
+ sb.Append(DestroyableSingleton<TranslationController>.Instance.GetString(TaskTypes.RestoreOxy));
+ sb.Append(" ");
+ sb.Append(Mathf.CeilToInt(this.reactor.Countdown));
+ sb.AppendLine(string.Format(" ({0}/{1})[]", this.reactor.UserCount, 2));
+ }
+ else
+ {
+ sb.AppendLine(color.ToTextColor() + "Oxygen depleting[]");
+ }
+ for (int i = 0; i < this.Arrows.Length; i++)
+ {
+ try
+ {
+ this.Arrows[i].image.color = color;
+ }
+ catch
+ {
+ }
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/NoShadowBehaviour.cs b/Client/Assembly-CSharp/NoShadowBehaviour.cs
new file mode 100644
index 0000000..67023ce
--- /dev/null
+++ b/Client/Assembly-CSharp/NoShadowBehaviour.cs
@@ -0,0 +1,55 @@
+using System;
+using UnityEngine;
+
+public class NoShadowBehaviour : MonoBehaviour
+{
+ public Renderer rend;
+
+ public bool didHit;
+
+ public Renderer shadowChild;
+
+ public void Start()
+ {
+ LightSource.NoShadows.Add(base.gameObject, this);
+ }
+
+ public void OnDestroy()
+ {
+ LightSource.NoShadows.Remove(base.gameObject);
+ }
+
+ private void LateUpdate()
+ {
+ if (!PlayerControl.LocalPlayer)
+ {
+ return;
+ }
+ GameData.PlayerInfo data = PlayerControl.LocalPlayer.Data;
+ if (data != null && !data.IsDead)
+ {
+ if (this.didHit)
+ {
+ this.didHit = false;
+ ShipStatus instance = ShipStatus.Instance;
+ if (instance && instance.CalculateLightRadius(data) > instance.MaxLightRadius / 3f)
+ {
+ this.SetMaskFunction(8);
+ return;
+ }
+ }
+ this.SetMaskFunction(1);
+ return;
+ }
+ this.SetMaskFunction(8);
+ }
+
+ private void SetMaskFunction(int func)
+ {
+ this.rend.material.SetInt("_Mask", func);
+ if (this.shadowChild)
+ {
+ this.shadowChild.material.SetInt("_Mask", func);
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/NormalPlayerTask.cs b/Client/Assembly-CSharp/NormalPlayerTask.cs
new file mode 100644
index 0000000..bd5133a
--- /dev/null
+++ b/Client/Assembly-CSharp/NormalPlayerTask.cs
@@ -0,0 +1,284 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using UnityEngine;
+
+public class NormalPlayerTask : PlayerTask
+{
+ public override int TaskStep
+ {
+ get
+ {
+ return this.taskStep;
+ }
+ }
+
+ public override bool IsComplete
+ {
+ get
+ {
+ return this.taskStep >= this.MaxStep;
+ }
+ }
+
+ public int taskStep;
+
+ public int MaxStep;
+
+ public bool ShowTaskStep = true;
+
+ public bool ShowTaskTimer;
+
+ public NormalPlayerTask.TimerState TimerStarted;
+
+ public float TaskTimer;
+
+ public byte[] Data;
+
+ public ArrowBehaviour Arrow;
+
+ public enum TimerState
+ {
+ NotStarted,
+ Started,
+ Finished
+ }
+
+ public override void Initialize()
+ {
+ if (this.Arrow && !base.Owner.AmOwner)
+ {
+ this.Arrow.gameObject.SetActive(false);
+ }
+ this.HasLocation = true;
+ this.LocationDirty = true;
+ TaskTypes taskType = this.TaskType;
+ switch (taskType)
+ {
+ case TaskTypes.PrimeShields:
+ {
+ this.Data = new byte[1];
+ int num = 0;
+ for (int i = 0; i < 7; i++)
+ {
+ byte b = (byte)(1 << i);
+ if (BoolRange.Next(0.7f))
+ {
+ byte[] data = this.Data;
+ int num2 = 0;
+ data[num2] |= b;
+ num++;
+ }
+ }
+ byte[] data2 = this.Data;
+ int num3 = 0;
+ data2[num3] &= 118;
+ return;
+ }
+ case TaskTypes.FuelEngines:
+ this.Data = new byte[2];
+ return;
+ case TaskTypes.ChartCourse:
+ this.Data = new byte[4];
+ return;
+ case TaskTypes.StartReactor:
+ this.Data = new byte[6];
+ return;
+ case TaskTypes.SwipeCard:
+ case TaskTypes.ClearAsteroids:
+ case TaskTypes.UploadData:
+ case TaskTypes.EmptyChute:
+ case TaskTypes.EmptyGarbage:
+ break;
+ case TaskTypes.InspectSample:
+ this.Data = new byte[2];
+ return;
+ case TaskTypes.AlignEngineOutput:
+ this.Data = new byte[2];
+ this.Data[0] = AlignGame.ToByte((float)IntRange.RandomSign() * FloatRange.Next(1f, 3f));
+ this.Data[1] = (byte)(IntRange.RandomSign() * IntRange.Next(25, 255));
+ return;
+ case TaskTypes.FixWiring:
+ {
+ this.Data = new byte[this.MaxStep];
+ List<global::Console> list = (from t in ShipStatus.Instance.AllConsoles
+ where t.TaskTypes.Contains(TaskTypes.FixWiring)
+ select t).ToList<global::Console>();
+ List<global::Console> list2 = new List<global::Console>(list);
+ for (int j = 0; j < this.Data.Length; j++)
+ {
+ int index = list2.RandomIdx<global::Console>();
+ this.Data[j] = (byte)list2[index].ConsoleId;
+ list2.RemoveAt(index);
+ }
+ Array.Sort<byte>(this.Data);
+ global::Console console = list.First((global::Console v) => v.ConsoleId == (int)this.Data[0]);
+ this.StartAt = console.Room;
+ break;
+ }
+ default:
+ if (taskType == TaskTypes.EnterIdCode)
+ {
+ this.Data = BitConverter.GetBytes(IntRange.Next(1, 99999));
+ return;
+ }
+ break;
+ }
+ }
+
+ public void NextStep()
+ {
+ this.taskStep++;
+ this.UpdateArrow();
+ if (this.taskStep >= this.MaxStep)
+ {
+ this.taskStep = this.MaxStep;
+ if (PlayerControl.LocalPlayer)
+ {
+ if (DestroyableSingleton<HudManager>.InstanceExists)
+ {
+ DestroyableSingleton<HudManager>.Instance.ShowTaskComplete();
+ StatsManager instance = StatsManager.Instance;
+ uint num = instance.TasksCompleted;
+ instance.TasksCompleted = num + 1U;
+ if (PlayerTask.AllTasksCompleted(PlayerControl.LocalPlayer))
+ {
+ StatsManager instance2 = StatsManager.Instance;
+ num = instance2.CompletedAllTasks;
+ instance2.CompletedAllTasks = num + 1U;
+ }
+ }
+ PlayerControl.LocalPlayer.RpcCompleteTask(base.Id);
+ return;
+ }
+ }
+ else if (this.ShowTaskStep && Constants.ShouldPlaySfx())
+ {
+ SoundManager.Instance.PlaySound(DestroyableSingleton<HudManager>.Instance.TaskUpdateSound, false, 1f);
+ }
+ }
+
+ public void UpdateArrow()
+ {
+ if (!this.Arrow)
+ {
+ return;
+ }
+ if (!base.Owner.AmOwner)
+ {
+ this.Arrow.gameObject.SetActive(false);
+ return;
+ }
+ if (!this.IsComplete)
+ {
+ this.Arrow.gameObject.SetActive(true);
+ if (this.TaskType == TaskTypes.FixWiring)
+ {
+ global::Console console3 = base.FindSpecialConsole((global::Console c) => c.TaskTypes.Contains(TaskTypes.FixWiring) && c.ConsoleId == (int)this.Data[this.taskStep]);
+ this.Arrow.target = console3.transform.position;
+ this.StartAt = console3.Room;
+ }
+ else if (this.TaskType == TaskTypes.AlignEngineOutput)
+ {
+ if (AlignGame.IsSuccess(this.Data[0]))
+ {
+ this.Arrow.target = base.FindSpecialConsole((global::Console c) => c.TaskTypes.Contains(TaskTypes.AlignEngineOutput) && c.ConsoleId == 1).transform.position;
+ this.StartAt = SystemTypes.UpperEngine;
+ }
+ else
+ {
+ this.Arrow.target = base.FindSpecialConsole((global::Console console) => console.TaskTypes.Contains(TaskTypes.AlignEngineOutput) && console.ConsoleId == 0).transform.position;
+ this.StartAt = SystemTypes.LowerEngine;
+ }
+ }
+ else
+ {
+ global::Console console2 = base.FindObjectPos();
+ this.Arrow.target = console2.transform.position;
+ this.StartAt = console2.Room;
+ }
+ this.LocationDirty = true;
+ return;
+ }
+ this.Arrow.gameObject.SetActive(false);
+ }
+
+ private void FixedUpdate()
+ {
+ if (this.TimerStarted == NormalPlayerTask.TimerState.Started)
+ {
+ this.TaskTimer -= Time.fixedDeltaTime;
+ if (this.TaskTimer <= 0f)
+ {
+ this.TaskTimer = 0f;
+ this.TimerStarted = NormalPlayerTask.TimerState.Finished;
+ }
+ }
+ }
+
+ public override bool ValidConsole(global::Console console)
+ {
+ if (this.TaskType == TaskTypes.FixWiring)
+ {
+ return console.TaskTypes.Contains(this.TaskType) && console.ConsoleId == (int)this.Data[this.taskStep];
+ }
+ if (this.TaskType == TaskTypes.AlignEngineOutput)
+ {
+ return console.TaskTypes.Contains(this.TaskType) && !AlignGame.IsSuccess(this.Data[console.ConsoleId]);
+ }
+ if (this.TaskType == TaskTypes.FuelEngines)
+ {
+ return (console.TaskTypes.Contains(this.TaskType) && console.ConsoleId == (int)this.Data[1]) || console.ValidTasks.Any((TaskSet set) => this.TaskType == set.taskType && set.taskStep.Contains((int)this.Data[1]));
+ }
+ return console.TaskTypes.Any((TaskTypes tt) => tt == this.TaskType) || console.ValidTasks.Any((TaskSet set) => this.TaskType == set.taskType && set.taskStep.Contains(this.taskStep));
+ }
+
+ public override void Complete()
+ {
+ this.taskStep = this.MaxStep;
+ }
+
+ public override void AppendTaskText(StringBuilder sb)
+ {
+ bool flag = this.ShouldYellowText();
+ if (flag)
+ {
+ if (this.IsComplete)
+ {
+ sb.Append("[00DD00FF]");
+ }
+ else
+ {
+ sb.Append("[FFFF00FF]");
+ }
+ }
+ sb.Append(DestroyableSingleton<TranslationController>.Instance.GetString(this.StartAt));
+ sb.Append(": ");
+ sb.Append(DestroyableSingleton<TranslationController>.Instance.GetString(this.TaskType));
+ if (this.ShowTaskTimer && this.TimerStarted == NormalPlayerTask.TimerState.Started)
+ {
+ sb.Append(" (");
+ sb.Append((int)this.TaskTimer);
+ sb.Append("s)");
+ }
+ else if (this.ShowTaskStep)
+ {
+ sb.Append(" (");
+ sb.Append(this.taskStep);
+ sb.Append("/");
+ sb.Append(this.MaxStep);
+ sb.Append(")");
+ }
+ if (flag)
+ {
+ sb.Append("[]");
+ }
+ sb.AppendLine();
+ }
+
+ private bool ShouldYellowText()
+ {
+ return (this.TaskType == TaskTypes.FuelEngines && this.Data[1] > 0) || this.taskStep > 0 || this.TimerStarted > NormalPlayerTask.TimerState.NotStarted;
+ }
+}
diff --git a/Client/Assembly-CSharp/NotificationPopper.cs b/Client/Assembly-CSharp/NotificationPopper.cs
new file mode 100644
index 0000000..8a98115
--- /dev/null
+++ b/Client/Assembly-CSharp/NotificationPopper.cs
@@ -0,0 +1,58 @@
+using System;
+using System.Text;
+using UnityEngine;
+
+public class NotificationPopper : MonoBehaviour
+{
+ public TextRenderer TextArea;
+
+ public float zPos = -350f;
+
+ private float alphaTimer;
+
+ public float ShowDuration = 5f;
+
+ public float FadeDuration = 1f;
+
+ public Color textColor = Color.white;
+
+ private StringBuilder builder = new StringBuilder();
+
+ public AudioClip NotificationSound;
+
+ public void Update()
+ {
+ if (this.alphaTimer > 0f)
+ {
+ float num = Camera.main.orthographicSize * Camera.main.aspect;
+ if (!DestroyableSingleton<HudManager>.Instance.TaskText.isActiveAndEnabled)
+ {
+ float height = DestroyableSingleton<HudManager>.Instance.GameSettings.Height;
+ Transform transform = DestroyableSingleton<HudManager>.Instance.GameSettings.transform;
+ base.transform.localPosition = new Vector3(-num + 0.1f, transform.localPosition.y - height, this.zPos);
+ }
+ else
+ {
+ float height2 = DestroyableSingleton<HudManager>.Instance.TaskText.Height;
+ Transform parent = DestroyableSingleton<HudManager>.Instance.TaskText.transform.parent;
+ base.transform.localPosition = new Vector3(-num + 0.1f, parent.localPosition.y - height2 - 0.2f, this.zPos);
+ }
+ this.alphaTimer -= Time.deltaTime;
+ this.textColor.a = Mathf.Clamp(this.alphaTimer / this.FadeDuration, 0f, 1f);
+ this.TextArea.Color = this.textColor;
+ if (this.alphaTimer <= 0f)
+ {
+ this.builder.Clear();
+ this.TextArea.Text = string.Empty;
+ }
+ }
+ }
+
+ public void AddItem(string item)
+ {
+ this.builder.AppendLine(item);
+ this.TextArea.Text = this.builder.ToString();
+ this.alphaTimer = this.ShowDuration;
+ SoundManager.Instance.PlaySound(this.NotificationSound, false, 1f);
+ }
+}
diff --git a/Client/Assembly-CSharp/NumberOption.cs b/Client/Assembly-CSharp/NumberOption.cs
new file mode 100644
index 0000000..ebe2f94
--- /dev/null
+++ b/Client/Assembly-CSharp/NumberOption.cs
@@ -0,0 +1,111 @@
+using System;
+using UnityEngine;
+
+public class NumberOption : OptionBehaviour
+{
+ public TextRenderer TitleText;
+
+ public TextRenderer ValueText;
+
+ public float Value = 1f;
+
+ private float oldValue = float.MaxValue;
+
+ public float Increment;
+
+ public FloatRange ValidRange = new FloatRange(0f, 2f);
+
+ public string FormatString = "{0:0.0}x";
+
+ public bool ZeroIsInfinity;
+
+ public void OnEnable()
+ {
+ this.TitleText.Text = DestroyableSingleton<TranslationController>.Instance.GetString(this.Title, Array.Empty<object>());
+ this.ValueText.Text = string.Format(this.FormatString, this.Value);
+ GameOptionsData gameOptions = PlayerControl.GameOptions;
+ StringNames title = this.Title;
+ switch (title)
+ {
+ case StringNames.GameNumImpostors:
+ this.Value = (float)gameOptions.NumImpostors;
+ return;
+ case StringNames.GameNumMeetings:
+ this.Value = (float)gameOptions.NumEmergencyMeetings;
+ return;
+ case StringNames.GameDiscussTime:
+ this.Value = (float)gameOptions.DiscussionTime;
+ return;
+ case StringNames.GameVotingTime:
+ this.Value = (float)gameOptions.VotingTime;
+ return;
+ case StringNames.GamePlayerSpeed:
+ this.Value = gameOptions.PlayerSpeedMod;
+ return;
+ case StringNames.GameCrewLight:
+ this.Value = gameOptions.CrewLightMod;
+ return;
+ case StringNames.GameImpostorLight:
+ this.Value = gameOptions.ImpostorLightMod;
+ return;
+ case StringNames.GameKillCooldown:
+ this.Value = gameOptions.KillCooldown;
+ return;
+ case StringNames.GameKillDistance:
+ break;
+ case StringNames.GameCommonTasks:
+ this.Value = (float)gameOptions.NumCommonTasks;
+ return;
+ case StringNames.GameLongTasks:
+ this.Value = (float)gameOptions.NumLongTasks;
+ return;
+ case StringNames.GameShortTasks:
+ this.Value = (float)gameOptions.NumShortTasks;
+ return;
+ default:
+ if (title == StringNames.GameEmergencyCooldown)
+ {
+ this.Value = (float)gameOptions.EmergencyCooldown;
+ return;
+ }
+ break;
+ }
+ Debug.Log("Ono, unrecognized setting: " + this.Title);
+ }
+
+ private void FixedUpdate()
+ {
+ if (this.oldValue != this.Value)
+ {
+ this.oldValue = this.Value;
+ if (this.ZeroIsInfinity && Mathf.Abs(this.Value) < 0.0001f)
+ {
+ this.ValueText.Text = string.Format(this.FormatString, "∞");
+ return;
+ }
+ this.ValueText.Text = string.Format(this.FormatString, this.Value);
+ }
+ }
+
+ public void Increase()
+ {
+ this.Value = this.ValidRange.Clamp(this.Value + this.Increment);
+ this.OnValueChanged(this);
+ }
+
+ public void Decrease()
+ {
+ this.Value = this.ValidRange.Clamp(this.Value - this.Increment);
+ this.OnValueChanged(this);
+ }
+
+ public override float GetFloat()
+ {
+ return this.Value;
+ }
+
+ public override int GetInt()
+ {
+ return (int)this.Value;
+ }
+}
diff --git a/Client/Assembly-CSharp/ObjectPoolBehavior.cs b/Client/Assembly-CSharp/ObjectPoolBehavior.cs
new file mode 100644
index 0000000..657837b
--- /dev/null
+++ b/Client/Assembly-CSharp/ObjectPoolBehavior.cs
@@ -0,0 +1,138 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class ObjectPoolBehavior : IObjectPool
+{
+ public override int InUse
+ {
+ get
+ {
+ return this.activeChildren.Count;
+ }
+ }
+
+ public override int NotInUse
+ {
+ get
+ {
+ return this.inactiveChildren.Count;
+ }
+ }
+
+ public int poolSize = 20;
+
+ [SerializeField]
+ private List<PoolableBehavior> inactiveChildren = new List<PoolableBehavior>();
+
+ [SerializeField]
+ public List<PoolableBehavior> activeChildren = new List<PoolableBehavior>();
+
+ public PoolableBehavior Prefab;
+
+ public bool AutoInit;
+
+ public bool DetachOnGet;
+
+ public virtual void Awake()
+ {
+ if (this.AutoInit)
+ {
+ this.InitPool(this.Prefab);
+ }
+ }
+
+ public void InitPool(PoolableBehavior prefab)
+ {
+ this.AutoInit = false;
+ for (int i = 0; i < this.poolSize; i++)
+ {
+ this.CreateOneInactive(prefab);
+ }
+ }
+
+ private void CreateOneInactive(PoolableBehavior prefab)
+ {
+ PoolableBehavior poolableBehavior = UnityEngine.Object.Instantiate<PoolableBehavior>(prefab);
+ poolableBehavior.transform.SetParent(base.transform);
+ poolableBehavior.gameObject.SetActive(false);
+ poolableBehavior.OwnerPool = this;
+ this.inactiveChildren.Add(poolableBehavior);
+ }
+
+ public void ReclaimOldest()
+ {
+ if (this.activeChildren.Count > 0)
+ {
+ this.Reclaim(this.activeChildren[0]);
+ return;
+ }
+ this.InitPool(this.Prefab);
+ }
+
+ public void ReclaimAll()
+ {
+ foreach (PoolableBehavior obj in this.activeChildren.ToArray())
+ {
+ this.Reclaim(obj);
+ }
+ }
+
+ public override T Get<T>()
+ {
+ List<PoolableBehavior> obj = this.inactiveChildren;
+ PoolableBehavior poolableBehavior;
+ lock (obj)
+ {
+ if (this.inactiveChildren.Count == 0)
+ {
+ if (this.activeChildren.Count == 0)
+ {
+ this.InitPool(this.Prefab);
+ }
+ else
+ {
+ this.CreateOneInactive(this.Prefab);
+ }
+ }
+ poolableBehavior = this.inactiveChildren[this.inactiveChildren.Count - 1];
+ this.inactiveChildren.RemoveAt(this.inactiveChildren.Count - 1);
+ this.activeChildren.Add(poolableBehavior);
+ }
+ if (this.DetachOnGet)
+ {
+ poolableBehavior.transform.SetParent(null, false);
+ }
+ poolableBehavior.gameObject.SetActive(true);
+ poolableBehavior.Reset();
+ return poolableBehavior as T;
+ }
+
+ public override void Reclaim(PoolableBehavior obj)
+ {
+ if (!this)
+ {
+ DefaultPool.Instance.Reclaim(obj);
+ return;
+ }
+ obj.gameObject.SetActive(false);
+ obj.transform.SetParent(base.transform);
+ List<PoolableBehavior> obj2 = this.inactiveChildren;
+ lock (obj2)
+ {
+ if (this.activeChildren.Remove(obj))
+ {
+ this.inactiveChildren.Add(obj);
+ }
+ else if (this.inactiveChildren.Contains(obj))
+ {
+ Debug.Log("ObjectPoolBehavior: :| Something was reclaimed without being gotten");
+ }
+ else
+ {
+ Debug.Log("ObjectPoolBehavior: Destroying this thing I don't own");
+ UnityEngine.Object.Destroy(obj.gameObject);
+ }
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/OffsetAdjustment.cs b/Client/Assembly-CSharp/OffsetAdjustment.cs
new file mode 100644
index 0000000..83e6b1c
--- /dev/null
+++ b/Client/Assembly-CSharp/OffsetAdjustment.cs
@@ -0,0 +1,11 @@
+using System;
+
+[Serializable]
+public class OffsetAdjustment
+{
+ public char Char;
+
+ public int OffsetX;
+
+ public int OffsetY;
+}
diff --git a/Client/Assembly-CSharp/OneWayShadows.cs b/Client/Assembly-CSharp/OneWayShadows.cs
new file mode 100644
index 0000000..e5aff45
--- /dev/null
+++ b/Client/Assembly-CSharp/OneWayShadows.cs
@@ -0,0 +1,22 @@
+using System;
+using UnityEngine;
+
+public class OneWayShadows : MonoBehaviour
+{
+ public Collider2D RoomCollider;
+
+ public void Start()
+ {
+ LightSource.OneWayShadows.Add(base.gameObject, this);
+ }
+
+ public void OnDestroy()
+ {
+ LightSource.OneWayShadows.Remove(base.gameObject);
+ }
+
+ public bool IsIgnored(LightSource lightSource)
+ {
+ return this.RoomCollider.OverlapPoint(lightSource.transform.position);
+ }
+}
diff --git a/Client/Assembly-CSharp/OptionBehaviour.cs b/Client/Assembly-CSharp/OptionBehaviour.cs
new file mode 100644
index 0000000..f17b80f
--- /dev/null
+++ b/Client/Assembly-CSharp/OptionBehaviour.cs
@@ -0,0 +1,33 @@
+using System;
+using UnityEngine;
+
+public abstract class OptionBehaviour : MonoBehaviour
+{
+ public StringNames Title;
+
+ public Action<OptionBehaviour> OnValueChanged;
+
+ public virtual float GetFloat()
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual int GetInt()
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual bool GetBool()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void SetAsPlayer()
+ {
+ PassiveButton[] componentsInChildren = base.GetComponentsInChildren<PassiveButton>();
+ for (int i = 0; i < componentsInChildren.Length; i++)
+ {
+ componentsInChildren[i].gameObject.SetActive(false);
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/OptionsConsole.cs b/Client/Assembly-CSharp/OptionsConsole.cs
new file mode 100644
index 0000000..4d80de9
--- /dev/null
+++ b/Client/Assembly-CSharp/OptionsConsole.cs
@@ -0,0 +1,64 @@
+using System;
+using UnityEngine;
+
+public class OptionsConsole : MonoBehaviour, IUsable
+{
+ public float UsableDistance
+ {
+ get
+ {
+ return 1f;
+ }
+ }
+
+ public float PercentCool
+ {
+ get
+ {
+ return 0f;
+ }
+ }
+
+ public CustomPlayerMenu MenuPrefab;
+
+ public SpriteRenderer Outline;
+
+ public float CanUse(GameData.PlayerInfo pc, out bool canUse, out bool couldUse)
+ {
+ float num = float.MaxValue;
+ PlayerControl @object = pc.Object;
+ couldUse = @object.CanMove;
+ canUse = couldUse;
+ if (canUse)
+ {
+ num = Vector2.Distance(@object.GetTruePosition(), base.transform.position);
+ canUse &= (num <= this.UsableDistance);
+ }
+ return num;
+ }
+
+ public void SetOutline(bool on, bool mainTarget)
+ {
+ if (this.Outline)
+ {
+ this.Outline.material.SetFloat("_Outline", (float)(on ? 1 : 0));
+ this.Outline.material.SetColor("_OutlineColor", Color.white);
+ this.Outline.material.SetColor("_AddColor", mainTarget ? Color.white : Color.clear);
+ }
+ }
+
+ public void Use()
+ {
+ bool flag;
+ bool flag2;
+ this.CanUse(PlayerControl.LocalPlayer.Data, out flag, out flag2);
+ if (!flag)
+ {
+ return;
+ }
+ PlayerControl.LocalPlayer.NetTransform.Halt();
+ CustomPlayerMenu customPlayerMenu = UnityEngine.Object.Instantiate<CustomPlayerMenu>(this.MenuPrefab);
+ customPlayerMenu.transform.SetParent(Camera.main.transform, false);
+ customPlayerMenu.transform.localPosition = new Vector3(0f, 0f, -20f);
+ }
+}
diff --git a/Client/Assembly-CSharp/OptionsMenuBehaviour.cs b/Client/Assembly-CSharp/OptionsMenuBehaviour.cs
new file mode 100644
index 0000000..fffe2b4
--- /dev/null
+++ b/Client/Assembly-CSharp/OptionsMenuBehaviour.cs
@@ -0,0 +1,200 @@
+using System;
+using UnityEngine;
+
+public class OptionsMenuBehaviour : MonoBehaviour, ITranslatedText
+{
+ public bool IsOpen
+ {
+ get
+ {
+ return base.isActiveAndEnabled;
+ }
+ }
+
+ public SpriteRenderer Background;
+
+ public SpriteRenderer JoystickButton;
+
+ public SpriteRenderer TouchButton;
+
+ public SlideBar JoystickSizeSlider;
+
+ public FloatRange JoystickSizes = new FloatRange(0.5f, 1.5f);
+
+ public SlideBar SoundSlider;
+
+ public SlideBar MusicSlider;
+
+ public ToggleButtonBehaviour SendTelemButton;
+
+ public ToggleButtonBehaviour PersonalizedAdsButton;
+
+ public ToggleButtonBehaviour CensorChatButton;
+
+ public bool Toggle = true;
+
+ public TabGroup[] Tabs;
+
+ public void OpenTabGroup(TabGroup selected)
+ {
+ selected.Open();
+ for (int i = 0; i < this.Tabs.Length; i++)
+ {
+ TabGroup tabGroup = this.Tabs[i];
+ if (!(tabGroup == selected))
+ {
+ tabGroup.Close();
+ }
+ }
+ }
+
+ private void Update()
+ {
+ if (Input.GetKeyUp(KeyCode.Escape))
+ {
+ this.Close();
+ }
+ }
+
+ public void Start()
+ {
+ DestroyableSingleton<TranslationController>.Instance.ActiveTexts.Add(this);
+ }
+
+ public void OnDestroy()
+ {
+ DestroyableSingleton<TranslationController>.Instance.ActiveTexts.Remove(this);
+ }
+
+ public void ResetText()
+ {
+ this.JoystickButton.transform.parent.GetComponentInChildren<TextRenderer>().Text = DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.SettingsMouseMode, Array.Empty<object>());
+ this.TouchButton.transform.parent.GetComponentInChildren<TextRenderer>().Text = DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.SettingsKeyboardMode, Array.Empty<object>());
+ this.JoystickSizeSlider.gameObject.SetActive(false);
+ }
+
+ public void Open()
+ {
+ this.ResetText();
+ if (base.gameObject.activeSelf)
+ {
+ if (this.Toggle)
+ {
+ base.GetComponent<TransitionOpen>().Close();
+ }
+ return;
+ }
+ this.OpenTabGroup(this.Tabs[0]);
+ this.UpdateButtons();
+ base.gameObject.SetActive(true);
+ }
+
+ public void SetControlType(int i)
+ {
+ SaveManager.TouchConfig = i;
+ this.UpdateButtons();
+ if (DestroyableSingleton<HudManager>.InstanceExists)
+ {
+ DestroyableSingleton<HudManager>.Instance.SetTouchType(i);
+ }
+ }
+
+ public void UpdateJoystickSize(SlideBar slider)
+ {
+ SaveManager.JoystickSize = this.JoystickSizes.Lerp(slider.Value);
+ if (DestroyableSingleton<HudManager>.InstanceExists)
+ {
+ DestroyableSingleton<HudManager>.Instance.SetJoystickSize(SaveManager.JoystickSize);
+ }
+ }
+
+ public void ToggleSendTelemetry()
+ {
+ SaveManager.SendTelemetry = !SaveManager.SendTelemetry;
+ this.UpdateButtons();
+ }
+
+ public void ToggleSendName()
+ {
+ SaveManager.SendName = !SaveManager.SendName;
+ this.UpdateButtons();
+ }
+
+ public void UpdateSfxVolume(SlideBar button)
+ {
+ SaveManager.SfxVolume = button.Value;
+ SoundManager.Instance.ChangeSfxVolume(button.Value);
+ }
+
+ public void UpdateMusicVolume(SlideBar button)
+ {
+ SaveManager.MusicVolume = button.Value;
+ SoundManager.Instance.ChangeMusicVolume(button.Value);
+ }
+
+ public void TogglePersonalizedAd()
+ {
+ ShowAdsState showAdsState = SaveManager.ShowAdsScreen & (ShowAdsState)127;
+ if (showAdsState != ShowAdsState.Personalized)
+ {
+ if (showAdsState == ShowAdsState.NonPersonalized)
+ {
+ SaveManager.ShowAdsScreen = ShowAdsState.Accepted;
+ goto IL_30;
+ }
+ if (showAdsState == ShowAdsState.Purchased)
+ {
+ goto IL_30;
+ }
+ }
+ SaveManager.ShowAdsScreen = (ShowAdsState)129;
+ IL_30:
+ this.UpdateButtons();
+ }
+
+ public void ToggleCensorChat()
+ {
+ SaveManager.CensorChat = !SaveManager.CensorChat;
+ this.UpdateButtons();
+ }
+
+ public void UpdateButtons()
+ {
+ if (SaveManager.TouchConfig == 0)
+ {
+ this.JoystickButton.color = new Color32(0, byte.MaxValue, 42, byte.MaxValue);
+ this.TouchButton.color = Color.white;
+ this.JoystickSizeSlider.enabled = true;
+ this.JoystickSizeSlider.OnEnable();
+ }
+ else
+ {
+ this.JoystickButton.color = Color.white;
+ this.TouchButton.color = new Color32(0, byte.MaxValue, 42, byte.MaxValue);
+ this.JoystickSizeSlider.enabled = false;
+ this.JoystickSizeSlider.OnDisable();
+ }
+ this.JoystickSizeSlider.Value = this.JoystickSizes.ReverseLerp(SaveManager.JoystickSize);
+ this.SoundSlider.Value = SaveManager.SfxVolume;
+ this.MusicSlider.Value = SaveManager.MusicVolume;
+ if (this.SendTelemButton)
+ {
+ this.SendTelemButton.UpdateText(SaveManager.SendTelemetry);
+ }
+ this.CensorChatButton.UpdateText(SaveManager.CensorChat);
+ if (this.PersonalizedAdsButton)
+ {
+ if (SaveManager.ShowAdsScreen.HasFlag(ShowAdsState.Purchased) || SaveManager.BoughtNoAds)
+ {
+ this.PersonalizedAdsButton.transform.parent.gameObject.SetActive(false);
+ return;
+ }
+ this.PersonalizedAdsButton.UpdateText(!SaveManager.ShowAdsScreen.HasFlag(ShowAdsState.NonPersonalized));
+ }
+ }
+
+ public void Close()
+ {
+ base.gameObject.SetActive(false);
+ }
+}
diff --git a/Client/Assembly-CSharp/OverlayKillAnimation.cs b/Client/Assembly-CSharp/OverlayKillAnimation.cs
new file mode 100644
index 0000000..d6f711e
--- /dev/null
+++ b/Client/Assembly-CSharp/OverlayKillAnimation.cs
@@ -0,0 +1,150 @@
+using System;
+using System.Collections;
+using PowerTools;
+using UnityEngine;
+
+public class OverlayKillAnimation : MonoBehaviour
+{
+ public KillAnimType KillType;
+
+ public PoolablePlayer killerParts;
+
+ public PoolablePlayer victimParts;
+
+ private uint victimHat;
+
+ public AudioClip Stinger;
+
+ public AudioClip Sfx;
+
+ public float StingerVolume = 0.6f;
+
+ public void Begin(PlayerControl killer, GameData.PlayerInfo vInfo)
+ {
+ if (this.killerParts)
+ {
+ GameData.PlayerInfo kInfo = killer.Data;
+ PlayerControl.SetPlayerMaterialColors((int)kInfo.ColorId, this.killerParts.Body);
+ this.killerParts.Hands.ForEach(delegate(SpriteRenderer b)
+ {
+ PlayerControl.SetPlayerMaterialColors((int)kInfo.ColorId, b);
+ });
+ PlayerControl.SetHatImage(kInfo.HatId, this.killerParts.HatSlot);
+ switch (this.KillType)
+ {
+ case KillAnimType.Stab:
+ case KillAnimType.Neck:
+ PlayerControl.SetSkinImage(kInfo.SkinId, this.killerParts.SkinSlot);
+ break;
+ case KillAnimType.Tongue:
+ {
+ SkinData skinById = DestroyableSingleton<HatManager>.Instance.GetSkinById(kInfo.SkinId);
+ this.killerParts.SkinSlot.GetComponent<SpriteAnim>().Play(skinById.KillTongueImpostor, 1f);
+ break;
+ }
+ case KillAnimType.Shoot:
+ {
+ SkinData skinById2 = DestroyableSingleton<HatManager>.Instance.GetSkinById(kInfo.SkinId);
+ this.killerParts.SkinSlot.GetComponent<SpriteAnim>().Play(skinById2.KillShootImpostor, 1f);
+ break;
+ }
+ }
+ if (this.killerParts.PetSlot)
+ {
+ PetBehaviour petById = DestroyableSingleton<HatManager>.Instance.GetPetById(kInfo.PetId);
+ if (petById && petById.scaredClip)
+ {
+ this.killerParts.PetSlot.GetComponent<SpriteAnim>().Play(petById.idleClip, 1f);
+ this.killerParts.PetSlot.sharedMaterial = petById.rend.sharedMaterial;
+ PlayerControl.SetPlayerMaterialColors((int)kInfo.ColorId, this.killerParts.PetSlot);
+ }
+ else
+ {
+ this.killerParts.PetSlot.enabled = false;
+ }
+ }
+ }
+ if (vInfo != null && this.victimParts)
+ {
+ this.victimHat = vInfo.HatId;
+ PlayerControl.SetPlayerMaterialColors((int)vInfo.ColorId, this.victimParts.Body);
+ PlayerControl.SetHatImage(vInfo.HatId, this.victimParts.HatSlot);
+ SkinData skinById3 = DestroyableSingleton<HatManager>.Instance.GetSkinById(vInfo.SkinId);
+ switch (this.KillType)
+ {
+ case KillAnimType.Stab:
+ this.victimParts.SkinSlot.GetComponent<SpriteAnim>().Play(skinById3.KillStabVictim, 1f);
+ break;
+ case KillAnimType.Tongue:
+ this.victimParts.SkinSlot.GetComponent<SpriteAnim>().Play(skinById3.KillTongueVictim, 1f);
+ break;
+ case KillAnimType.Shoot:
+ this.victimParts.SkinSlot.GetComponent<SpriteAnim>().Play(skinById3.KillShootVictim, 1f);
+ break;
+ case KillAnimType.Neck:
+ this.victimParts.SkinSlot.GetComponent<SpriteAnim>().Play(skinById3.KillNeckVictim, 1f);
+ break;
+ }
+ if (this.victimParts.PetSlot)
+ {
+ PetBehaviour petById2 = DestroyableSingleton<HatManager>.Instance.GetPetById(vInfo.PetId);
+ if (petById2 && petById2.scaredClip)
+ {
+ this.victimParts.PetSlot.GetComponent<SpriteAnim>().Play(petById2.scaredClip, 1f);
+ this.victimParts.PetSlot.sharedMaterial = petById2.rend.sharedMaterial;
+ PlayerControl.SetPlayerMaterialColors((int)vInfo.ColorId, this.victimParts.PetSlot);
+ return;
+ }
+ this.victimParts.PetSlot.enabled = false;
+ }
+ }
+ }
+
+ public void SetHatFloor()
+ {
+ HatBehaviour hatById = DestroyableSingleton<HatManager>.Instance.GetHatById(this.victimHat);
+ if (!hatById)
+ {
+ return;
+ }
+ this.victimParts.HatSlot.sprite = hatById.FloorImage;
+ }
+
+ public void PlayKillSound()
+ {
+ if (Constants.ShouldPlaySfx())
+ {
+ SoundManager.Instance.PlaySound(this.Sfx, false, 1f).volume = 0.8f;
+ }
+ }
+
+ public IEnumerator WaitForFinish()
+ {
+ SpriteAnim[] anims = base.GetComponentsInChildren<SpriteAnim>();
+ if (anims.Length == 0)
+ {
+ yield return new WaitForSeconds(1f);
+ }
+ else
+ {
+ for (;;)
+ {
+ bool flag = false;
+ for (int i = 0; i < anims.Length; i++)
+ {
+ if (anims[i].IsPlaying(null))
+ {
+ flag = true;
+ break;
+ }
+ }
+ if (!flag)
+ {
+ break;
+ }
+ yield return null;
+ }
+ }
+ yield break;
+ }
+}
diff --git a/Client/Assembly-CSharp/Palette.cs b/Client/Assembly-CSharp/Palette.cs
new file mode 100644
index 0000000..044fa1a
--- /dev/null
+++ b/Client/Assembly-CSharp/Palette.cs
@@ -0,0 +1,67 @@
+using System;
+using UnityEngine;
+
+public static class Palette
+{
+ public static readonly Color DisabledGrey = new Color(0.3f, 0.3f, 0.3f, 1f);
+
+ public static readonly Color DisabledColor = new Color(1f, 1f, 1f, 0.3f);
+
+ public static readonly Color EnabledColor = new Color(1f, 1f, 1f, 1f);
+
+ public static readonly Color Black = new Color(0f, 0f, 0f, 1f);
+
+ public static readonly Color ClearWhite = new Color(1f, 1f, 1f, 0f);
+
+ public static readonly Color HalfWhite = new Color(1f, 1f, 1f, 0.5f);
+
+ public static readonly Color White = new Color(1f, 1f, 1f, 1f);
+
+ public static readonly Color LightBlue = new Color(0.5f, 0.5f, 1f);
+
+ public static readonly Color Blue = new Color(0.2f, 0.2f, 1f);
+
+ public static readonly Color Orange = new Color(1f, 0.6f, 0.005f);
+
+ public static readonly Color Purple = new Color(0.6f, 0.1f, 0.6f);
+
+ public static readonly Color Brown = new Color(0.72f, 0.43f, 0.11f);
+
+ public static readonly Color CrewmateBlue = new Color32(140, byte.MaxValue, byte.MaxValue, byte.MaxValue);
+
+ public static readonly Color ImpostorRed = new Color32(byte.MaxValue, 25, 25, byte.MaxValue);
+
+ public static readonly Color32[] PlayerColors = new Color32[]
+ {
+ new Color32(198, 17, 17, byte.MaxValue),
+ new Color32(19, 46, 210, byte.MaxValue),
+ new Color32(17, 128, 45, byte.MaxValue),
+ new Color32(238, 84, 187, byte.MaxValue),
+ new Color32(240, 125, 13, byte.MaxValue),
+ new Color32(246, 246, 87, byte.MaxValue),
+ new Color32(63, 71, 78, byte.MaxValue),
+ new Color32(215, 225, 241, byte.MaxValue),
+ new Color32(107, 47, 188, byte.MaxValue),
+ new Color32(113, 73, 30, byte.MaxValue),
+ new Color32(56, byte.MaxValue, 221, byte.MaxValue),
+ new Color32(80, 240, 57, byte.MaxValue)
+ };
+
+ public static readonly Color32[] ShadowColors = new Color32[]
+ {
+ new Color32(122, 8, 56, byte.MaxValue),
+ new Color32(9, 21, 142, byte.MaxValue),
+ new Color32(10, 77, 46, byte.MaxValue),
+ new Color32(172, 43, 174, byte.MaxValue),
+ new Color32(180, 62, 21, byte.MaxValue),
+ new Color32(195, 136, 34, byte.MaxValue),
+ new Color32(30, 31, 38, byte.MaxValue),
+ new Color32(132, 149, 192, byte.MaxValue),
+ new Color32(59, 23, 124, byte.MaxValue),
+ new Color32(94, 38, 21, byte.MaxValue),
+ new Color32(36, 169, 191, byte.MaxValue),
+ new Color32(21, 168, 66, byte.MaxValue)
+ };
+
+ public static readonly Color32 VisorColor = new Color32(149, 202, 220, byte.MaxValue);
+}
diff --git a/Client/Assembly-CSharp/ParallaxController.cs b/Client/Assembly-CSharp/ParallaxController.cs
new file mode 100644
index 0000000..892453d
--- /dev/null
+++ b/Client/Assembly-CSharp/ParallaxController.cs
@@ -0,0 +1,22 @@
+using System;
+using UnityEngine;
+
+public class ParallaxController : MonoBehaviour
+{
+ public float Rate;
+
+ private Camera cam;
+
+ public void Start()
+ {
+ this.cam = Camera.main;
+ }
+
+ private void Update()
+ {
+ Vector3 vector = base.transform.parent.position - this.cam.transform.position;
+ vector *= this.Rate;
+ vector.z = -this.Rate;
+ base.transform.localPosition = vector;
+ }
+}
diff --git a/Client/Assembly-CSharp/ParticleInfo.cs b/Client/Assembly-CSharp/ParticleInfo.cs
new file mode 100644
index 0000000..2c5da66
--- /dev/null
+++ b/Client/Assembly-CSharp/ParticleInfo.cs
@@ -0,0 +1,12 @@
+using System;
+using UnityEngine;
+
+[Serializable]
+public struct ParticleInfo
+{
+ public Vector3 Position;
+
+ public float Scale;
+
+ public float Timer;
+}
diff --git a/Client/Assembly-CSharp/PassiveButton.cs b/Client/Assembly-CSharp/PassiveButton.cs
new file mode 100644
index 0000000..f7e9337
--- /dev/null
+++ b/Client/Assembly-CSharp/PassiveButton.cs
@@ -0,0 +1,47 @@
+using System;
+using UnityEngine;
+using UnityEngine.Events;
+using UnityEngine.UI;
+
+public class PassiveButton : MonoBehaviour
+{
+ public bool OnUp = true;
+
+ public bool OnDown;
+
+ public Button.ButtonClickedEvent OnClick = new Button.ButtonClickedEvent();
+
+ public AudioClip ClickSound;
+
+ public UnityEvent OnMouseOver;
+
+ public UnityEvent OnMouseOut;
+
+ public Collider2D[] Colliders;
+
+ public void Start()
+ {
+ DestroyableSingleton<PassiveButtonManager>.Instance.RegisterOne(this);
+ if (this.Colliders == null || this.Colliders.Length == 0)
+ {
+ this.Colliders = base.GetComponents<Collider2D>();
+ }
+ }
+
+ public void DoClick()
+ {
+ if (this.ClickSound)
+ {
+ SoundManager.Instance.PlaySound(this.ClickSound, false, 1f);
+ }
+ this.OnClick.Invoke();
+ }
+
+ public void OnDestroy()
+ {
+ if (DestroyableSingleton<PassiveButtonManager>.InstanceExists)
+ {
+ DestroyableSingleton<PassiveButtonManager>.Instance.RemoveOne(this);
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/PassiveButtonManager.cs b/Client/Assembly-CSharp/PassiveButtonManager.cs
new file mode 100644
index 0000000..b45379b
--- /dev/null
+++ b/Client/Assembly-CSharp/PassiveButtonManager.cs
@@ -0,0 +1,256 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class PassiveButtonManager : DestroyableSingleton<PassiveButtonManager>
+{
+ public List<PassiveButton> Buttons = new List<PassiveButton>();
+
+ private List<IFocusHolder> FocusHolders = new List<IFocusHolder>();
+
+ private PassiveButton currentOver;
+
+ public Controller Controller = new Controller();
+
+ private PassiveButton currentDown;
+
+ private Collider2D[] results = new Collider2D[40];
+
+ private class DepthComparer : IComparer<PassiveButton>
+ {
+ public static readonly PassiveButtonManager.DepthComparer Instance = new PassiveButtonManager.DepthComparer();
+
+ public int Compare(PassiveButton x, PassiveButton y)
+ {
+ if (x == null)
+ {
+ return 1;
+ }
+ if (y == null)
+ {
+ return -1;
+ }
+ return x.transform.position.z.CompareTo(y.transform.position.z);
+ }
+ }
+
+ public void RegisterOne(PassiveButton button)
+ {
+ this.Buttons.Add(button);
+ }
+
+ public void RemoveOne(PassiveButton passiveButton)
+ {
+ this.Buttons.Remove(passiveButton);
+ }
+
+ public void RegisterOne(IFocusHolder focusHolder)
+ {
+ this.FocusHolders.Add(focusHolder);
+ }
+
+ public void RemoveOne(IFocusHolder focusHolder)
+ {
+ this.FocusHolders.Remove(focusHolder);
+ }
+
+ public void Update()
+ {
+ this.Controller.Update();
+ for (int i = 1; i < this.Buttons.Count; i++)
+ {
+ if (PassiveButtonManager.DepthComparer.Instance.Compare(this.Buttons[i - 1], this.Buttons[i]) > 0)
+ {
+ this.Buttons.Sort(PassiveButtonManager.DepthComparer.Instance);
+ break;
+ }
+ }
+ Vector2 position = this.Controller.Touches[0].Position;
+ int num = Physics2D.OverlapPointNonAlloc(position, this.results);
+ bool flag = false;
+ for (int j = 0; j < this.Buttons.Count; j++)
+ {
+ PassiveButton passiveButton = this.Buttons[j];
+ if (!passiveButton)
+ {
+ this.Buttons.RemoveAt(j);
+ j--;
+ }
+ else if (passiveButton.isActiveAndEnabled)
+ {
+ bool flag2 = false;
+ for (int k = 0; k < num; k++)
+ {
+ if (this.results[k].gameObject == passiveButton.gameObject)
+ {
+ flag2 = true;
+ break;
+ }
+ }
+ if (flag2)
+ {
+ flag = true;
+ if (passiveButton != this.currentOver)
+ {
+ if (this.currentOver)
+ {
+ this.currentOver.OnMouseOut.Invoke();
+ }
+ this.currentOver = passiveButton;
+ this.currentDown = null;
+ this.currentOver.OnMouseOver.Invoke();
+ break;
+ }
+ break;
+ }
+ }
+ }
+ if (!flag && this.currentOver)
+ {
+ this.currentOver.OnMouseOut.Invoke();
+ this.currentOver = null;
+ this.currentDown = null;
+ }
+ if (this.Controller.AnyTouchDown)
+ {
+ if (this.currentOver)
+ {
+ this.currentDown = this.currentOver;
+ if (this.currentOver.OnDown)
+ {
+ this.currentOver.DoClick();
+ }
+ }
+ this.HandleFocus(position);
+ return;
+ }
+ if (this.Controller.AnyTouchUp && this.currentDown)
+ {
+ if (this.currentDown.OnUp)
+ {
+ this.currentDown.DoClick();
+ }
+ this.currentDown = null;
+ }
+ }
+
+ private void CheckForDown()
+ {
+ Vector2 touch = this.GetTouch(true);
+ for (int i = 0; i < this.Buttons.Count; i++)
+ {
+ PassiveButton passiveButton = this.Buttons[i];
+ if (!passiveButton)
+ {
+ this.Buttons.RemoveAt(i);
+ i--;
+ }
+ else if (passiveButton.isActiveAndEnabled)
+ {
+ for (int j = 0; j < passiveButton.Colliders.Length; j++)
+ {
+ Collider2D collider2D = passiveButton.Colliders[j];
+ if (collider2D && collider2D.OverlapPoint(touch))
+ {
+ this.currentDown = passiveButton;
+ if (passiveButton.OnDown)
+ {
+ passiveButton.DoClick();
+ }
+ return;
+ }
+ }
+ }
+ }
+ this.HandleFocus(touch);
+ }
+
+ private void HandleFocus(Vector2 pt)
+ {
+ bool flag = false;
+ for (int i = 0; i < this.FocusHolders.Count; i++)
+ {
+ IFocusHolder focusHolder = this.FocusHolders[i];
+ if (!(focusHolder as MonoBehaviour))
+ {
+ this.FocusHolders.RemoveAt(i);
+ i--;
+ }
+ else if (focusHolder.CheckCollision(pt))
+ {
+ flag = true;
+ focusHolder.GiveFocus();
+ for (int j = 0; j < this.FocusHolders.Count; j++)
+ {
+ if (j != i)
+ {
+ this.FocusHolders[j].LoseFocus();
+ }
+ }
+ break;
+ }
+ }
+ if (!flag)
+ {
+ for (int k = 0; k < this.FocusHolders.Count; k++)
+ {
+ this.FocusHolders[k].LoseFocus();
+ }
+ }
+ }
+
+ private void HandleMouseOut(PassiveButton button)
+ {
+ if (this.currentOver == button)
+ {
+ button.OnMouseOut.Invoke();
+ this.currentOver = null;
+ }
+ }
+
+ private void CheckForUp()
+ {
+ if (!this.currentDown)
+ {
+ return;
+ }
+ PassiveButton passiveButton = this.currentDown;
+ this.currentDown = null;
+ if (!passiveButton.OnUp)
+ {
+ return;
+ }
+ Vector2 touch = this.GetTouch(false);
+ for (int i = 0; i < passiveButton.Colliders.Length; i++)
+ {
+ if (passiveButton.Colliders[i].OverlapPoint(touch))
+ {
+ if (passiveButton.OnUp)
+ {
+ passiveButton.DoClick();
+ }
+ return;
+ }
+ }
+ }
+
+ private Vector2 GetTouch(bool downOrUp)
+ {
+ if (downOrUp)
+ {
+ if (this.Controller.Touches[0].TouchStart)
+ {
+ return this.Controller.Touches[0].Position;
+ }
+ return this.Controller.Touches[1].Position;
+ }
+ else
+ {
+ if (this.Controller.Touches[0].TouchEnd)
+ {
+ return this.Controller.Touches[0].Position;
+ }
+ return this.Controller.Touches[1].Position;
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/PetBehaviour.cs b/Client/Assembly-CSharp/PetBehaviour.cs
new file mode 100644
index 0000000..bf94b13
--- /dev/null
+++ b/Client/Assembly-CSharp/PetBehaviour.cs
@@ -0,0 +1,140 @@
+using System;
+using PowerTools;
+using UnityEngine;
+
+public class PetBehaviour : MonoBehaviour, IBuyable
+{
+ public string ProdId
+ {
+ get
+ {
+ return this.ProductId;
+ }
+ }
+
+ public bool Visible
+ {
+ set
+ {
+ this.rend.enabled = value;
+ this.shadowRend.enabled = value;
+ }
+ }
+
+ private const float SnapDistance = 2f;
+
+ public bool Free;
+
+ public string ProductId;
+
+ public string StoreName;
+
+ public uint SteamId;
+
+ public int ItchId;
+
+ public string ItchUrl;
+
+ public PlayerControl Source;
+
+ public const float MinDistance = 0.2f;
+
+ public const float damping = 0.7f;
+
+ public const float Easing = 0.2f;
+
+ public const float Speed = 5f;
+
+ public float YOffset = -0.25f;
+
+ public SpriteAnim animator;
+
+ public SpriteRenderer rend;
+
+ public SpriteRenderer shadowRend;
+
+ public Rigidbody2D body;
+
+ public Collider2D Collider;
+
+ public AnimationClip idleClip;
+
+ public AnimationClip sadClip;
+
+ public AnimationClip scaredClip;
+
+ public AnimationClip walkClip;
+
+ private Vector2 GetTruePosition()
+ {
+ return base.transform.position + this.Collider.offset * 0.7f;
+ }
+
+ public void FixedUpdate()
+ {
+ if (!this.Source)
+ {
+ this.body.velocity = Vector2.zero;
+ return;
+ }
+ this.Visible = this.Source.Visible;
+ Vector2 truePosition = this.Source.GetTruePosition();
+ Vector2 truePosition2 = this.GetTruePosition();
+ Vector2 vector = this.body.velocity;
+ Vector2 a = truePosition - truePosition2;
+ float num = 0f;
+ if (this.Source.CanMove)
+ {
+ num = 0.2f;
+ }
+ if (a.sqrMagnitude > num)
+ {
+ if (a.sqrMagnitude > 2f)
+ {
+ base.transform.position = truePosition;
+ return;
+ }
+ a *= 5f * PlayerControl.GameOptions.PlayerSpeedMod;
+ vector = vector * 0.8f + a * 0.2f;
+ }
+ else
+ {
+ vector *= 0.7f;
+ }
+ AnimationClip currentAnimation = this.animator.GetCurrentAnimation();
+ if (vector.sqrMagnitude > 0.01f)
+ {
+ if (currentAnimation != this.walkClip)
+ {
+ this.animator.Play(this.walkClip, 1f);
+ }
+ if (vector.x < -0.01f)
+ {
+ this.rend.flipX = true;
+ }
+ else if (vector.x > 0.01f)
+ {
+ this.rend.flipX = false;
+ }
+ }
+ else if (currentAnimation == this.walkClip)
+ {
+ this.animator.Play(this.idleClip, 1f);
+ }
+ this.body.velocity = vector;
+ }
+
+ private void LateUpdate()
+ {
+ Vector3 localPosition = base.transform.localPosition;
+ localPosition.z = (localPosition.y + this.YOffset) / 1000f + 0.0002f;
+ base.transform.localPosition = localPosition;
+ }
+
+ public void SetMourning()
+ {
+ this.Source = null;
+ this.body.velocity = Vector2.zero;
+ this.animator.Play(this.sadClip, 1f);
+ }
+}
diff --git a/Client/Assembly-CSharp/PetsTab.cs b/Client/Assembly-CSharp/PetsTab.cs
new file mode 100644
index 0000000..2c362c3
--- /dev/null
+++ b/Client/Assembly-CSharp/PetsTab.cs
@@ -0,0 +1,78 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class PetsTab : MonoBehaviour
+{
+ public ColorChip ColorTabPrefab;
+
+ public SpriteRenderer DemoImage;
+
+ public SpriteRenderer HatImage;
+
+ public SpriteRenderer SkinImage;
+
+ public SpriteRenderer PetImage;
+
+ public FloatRange XRange = new FloatRange(1.5f, 3f);
+
+ public float YStart = 0.8f;
+
+ public float YOffset = 0.8f;
+
+ public int NumPerRow = 4;
+
+ public Scroller scroller;
+
+ private List<ColorChip> ColorChips = new List<ColorChip>();
+
+ public void OnEnable()
+ {
+ PlayerControl.SetPlayerMaterialColors((int)PlayerControl.LocalPlayer.Data.ColorId, this.DemoImage);
+ PlayerControl.SetHatImage(SaveManager.LastHat, this.HatImage);
+ PlayerControl.SetSkinImage(SaveManager.LastSkin, this.SkinImage);
+ PlayerControl.SetPetImage(SaveManager.LastPet, (int)PlayerControl.LocalPlayer.Data.ColorId, this.PetImage);
+ PetBehaviour[] unlockedPets = DestroyableSingleton<HatManager>.Instance.GetUnlockedPets();
+ for (int i = 0; i < unlockedPets.Length; i++)
+ {
+ PetBehaviour pet = unlockedPets[i];
+ float x = this.XRange.Lerp((float)(i % this.NumPerRow) / ((float)this.NumPerRow - 1f));
+ float y = this.YStart - (float)(i / this.NumPerRow) * this.YOffset;
+ ColorChip chip = UnityEngine.Object.Instantiate<ColorChip>(this.ColorTabPrefab, this.scroller.Inner);
+ chip.transform.localPosition = new Vector3(x, y, -1f);
+ chip.InUseForeground.SetActive(DestroyableSingleton<HatManager>.Instance.GetIdFromPet(pet) == SaveManager.LastPet);
+ chip.Button.OnClick.AddListener(delegate()
+ {
+ this.SelectPet(chip, pet);
+ });
+ PlayerControl.SetPetImage(pet, (int)PlayerControl.LocalPlayer.Data.ColorId, chip.Inner);
+ this.ColorChips.Add(chip);
+ }
+ this.scroller.YBounds.max = -(this.YStart - (float)(unlockedPets.Length / this.NumPerRow) * this.YOffset) - 3f;
+ }
+
+ public void OnDisable()
+ {
+ for (int i = 0; i < this.ColorChips.Count; i++)
+ {
+ UnityEngine.Object.Destroy(this.ColorChips[i].gameObject);
+ }
+ this.ColorChips.Clear();
+ }
+
+ private void SelectPet(ColorChip sender, PetBehaviour pet)
+ {
+ uint idFromPet = DestroyableSingleton<HatManager>.Instance.GetIdFromPet(pet);
+ SaveManager.LastPet = idFromPet;
+ PlayerControl.SetPetImage(pet, (int)PlayerControl.LocalPlayer.Data.ColorId, this.PetImage);
+ if (PlayerControl.LocalPlayer)
+ {
+ PlayerControl.LocalPlayer.RpcSetPet(idFromPet);
+ }
+ for (int i = 0; i < this.ColorChips.Count; i++)
+ {
+ ColorChip colorChip = this.ColorChips[i];
+ colorChip.InUseForeground.SetActive(colorChip == sender);
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/PhysicsHelpers.cs b/Client/Assembly-CSharp/PhysicsHelpers.cs
new file mode 100644
index 0000000..706073f
--- /dev/null
+++ b/Client/Assembly-CSharp/PhysicsHelpers.cs
@@ -0,0 +1,38 @@
+using System;
+using UnityEngine;
+
+public static class PhysicsHelpers
+{
+ private static RaycastHit2D[] castHits = new RaycastHit2D[20];
+
+ private static Vector2 temp = default(Vector2);
+
+ private static ContactFilter2D filter = new ContactFilter2D
+ {
+ useLayerMask = true
+ };
+
+ public static bool AnythingBetween(Vector2 source, Vector2 target, int layerMask, bool useTriggers)
+ {
+ PhysicsHelpers.filter.layerMask = layerMask;
+ PhysicsHelpers.filter.useTriggers = useTriggers;
+ PhysicsHelpers.temp.x = target.x - source.x;
+ PhysicsHelpers.temp.y = target.y - source.y;
+ return Physics2D.Raycast(source, PhysicsHelpers.temp, PhysicsHelpers.filter, PhysicsHelpers.castHits, PhysicsHelpers.temp.magnitude) > 0;
+ }
+
+ public static bool AnyNonTriggersBetween(Vector2 source, Vector2 dirNorm, float mag, int layerMask)
+ {
+ int num = Physics2D.RaycastNonAlloc(source, dirNorm, PhysicsHelpers.castHits, mag, layerMask);
+ bool result = false;
+ for (int i = 0; i < num; i++)
+ {
+ if (!PhysicsHelpers.castHits[i].collider.isTrigger)
+ {
+ result = true;
+ break;
+ }
+ }
+ return result;
+ }
+}
diff --git a/Client/Assembly-CSharp/PingTracker.cs b/Client/Assembly-CSharp/PingTracker.cs
new file mode 100644
index 0000000..727d71c
--- /dev/null
+++ b/Client/Assembly-CSharp/PingTracker.cs
@@ -0,0 +1,19 @@
+using System;
+using UnityEngine;
+
+public class PingTracker : MonoBehaviour
+{
+ public TextRenderer text;
+
+ private void Update()
+ {
+ if (AmongUsClient.Instance)
+ {
+ if (AmongUsClient.Instance.GameMode == GameModes.FreePlay)
+ {
+ base.gameObject.SetActive(false);
+ }
+ this.text.Text = string.Format("Ping: {0} ms", AmongUsClient.Instance.Ping);
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/PlayerAnimator.cs b/Client/Assembly-CSharp/PlayerAnimator.cs
new file mode 100644
index 0000000..dd48ace
--- /dev/null
+++ b/Client/Assembly-CSharp/PlayerAnimator.cs
@@ -0,0 +1,90 @@
+using System;
+using System.Collections;
+using PowerTools;
+using UnityEngine;
+
+public class PlayerAnimator : MonoBehaviour
+{
+ public float Speed = 2.5f;
+
+ public VirtualJoystick joystick;
+
+ public SpriteRenderer UseButton;
+
+ public FingerBehaviour finger;
+
+ public AnimationClip RunAnim;
+
+ public AnimationClip IdleAnim;
+
+ private Vector2 velocity;
+
+ [HideInInspector]
+ private SpriteAnim Animator;
+
+ [HideInInspector]
+ private SpriteRenderer rend;
+
+ public int NearbyConsoles;
+
+ private void Start()
+ {
+ this.Animator = base.GetComponent<SpriteAnim>();
+ this.rend = base.GetComponent<SpriteRenderer>();
+ this.rend.material.SetColor("_BackColor", Palette.ShadowColors[0]);
+ this.rend.material.SetColor("_BodyColor", Palette.PlayerColors[0]);
+ this.rend.material.SetColor("_VisorColor", Palette.VisorColor);
+ }
+
+ public void FixedUpdate()
+ {
+ base.transform.Translate(this.velocity * Time.fixedDeltaTime);
+ this.UseButton.enabled = (this.NearbyConsoles > 0);
+ }
+
+ public void LateUpdate()
+ {
+ if (this.velocity.sqrMagnitude >= 0.1f)
+ {
+ if (this.Animator.GetCurrentAnimation() != this.RunAnim)
+ {
+ this.Animator.Play(this.RunAnim, 1f);
+ }
+ this.rend.flipX = (this.velocity.x < 0f);
+ return;
+ }
+ if (this.Animator.GetCurrentAnimation() == this.RunAnim)
+ {
+ this.Animator.Play(this.IdleAnim, 1f);
+ }
+ }
+
+ public IEnumerator WalkPlayerTo(Vector2 worldPos, bool relax, float tolerance = 0.01f)
+ {
+ worldPos.y += 0.3636f;
+ if (!(this.joystick is DemoKeyboardStick))
+ {
+ this.finger.ClickOn();
+ }
+ for (;;)
+ {
+ Vector2 vector2;
+ Vector2 vector = vector2 = worldPos - base.transform.position;
+ if (vector2.sqrMagnitude <= tolerance)
+ {
+ break;
+ }
+ float d = Mathf.Clamp(vector.magnitude * 2f, 0.01f, 1f);
+ this.velocity = vector.normalized * this.Speed * d;
+ this.joystick.UpdateJoystick(this.finger, this.velocity, true);
+ yield return null;
+ }
+ if (relax)
+ {
+ this.finger.ClickOff();
+ this.velocity = Vector2.zero;
+ this.joystick.UpdateJoystick(this.finger, this.velocity, false);
+ }
+ yield break;
+ }
+}
diff --git a/Client/Assembly-CSharp/PlayerControl.cs b/Client/Assembly-CSharp/PlayerControl.cs
new file mode 100644
index 0000000..f0e5fbc
--- /dev/null
+++ b/Client/Assembly-CSharp/PlayerControl.cs
@@ -0,0 +1,1470 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using Assets.CoreScripts;
+using Hazel;
+using InnerNet;
+using PowerTools;
+using UnityEngine;
+
+public class PlayerControl : InnerNetObject
+{
+ public bool CanMove
+ {
+ get
+ {
+ return this.moveable && !Minigame.Instance && (!DestroyableSingleton<HudManager>.InstanceExists || (!DestroyableSingleton<HudManager>.Instance.Chat.IsOpen && !DestroyableSingleton<HudManager>.Instance.KillOverlay.IsOpen && !DestroyableSingleton<HudManager>.Instance.GameMenu.IsOpen)) && (!MapBehaviour.Instance || !MapBehaviour.Instance.IsOpenStopped) && !MeetingHud.Instance && !CustomPlayerMenu.Instance && !ExileController.Instance && !IntroCutscene.Instance;
+ }
+ }
+
+ public GameData.PlayerInfo Data
+ {
+ get
+ {
+ if (this._cachedData == null)
+ {
+ if (!GameData.Instance)
+ {
+ return null;
+ }
+ this._cachedData = GameData.Instance.GetPlayerById(this.PlayerId);
+ }
+ return this._cachedData;
+ }
+ }
+
+ public bool Visible
+ {
+ get
+ {
+ return this.myRend.enabled;
+ }
+ set
+ {
+ this.myRend.enabled = value;
+ this.MyPhysics.Skin.Visible = value;
+ this.HatRenderer.enabled = value;
+ this.nameText.gameObject.SetActive(value);
+ }
+ }
+
+ public byte PlayerId = byte.MaxValue;
+
+ public float MaxReportDistance = 5f;
+
+ public bool moveable = true;
+
+ public bool inVent;
+
+ public static PlayerControl LocalPlayer;
+
+ private GameData.PlayerInfo _cachedData;
+
+ public AudioSource FootSteps;
+
+ public AudioClip KillSfx;
+
+ public KillAnimation[] KillAnimations;
+
+ [SerializeField]
+ private float killTimer;
+
+ public int RemainingEmergencies;
+
+ public TextRenderer nameText;
+
+ public LightSource LightPrefab;
+
+ private LightSource myLight;
+
+ [HideInInspector]
+ public Collider2D Collider;
+
+ [HideInInspector]
+ public PlayerPhysics MyPhysics;
+
+ [HideInInspector]
+ public CustomNetworkTransform NetTransform;
+
+ public PetBehaviour CurrentPet;
+
+ public SpriteRenderer HatRenderer;
+
+ private SpriteRenderer myRend;
+
+ private Collider2D[] hitBuffer = new Collider2D[20];
+
+ public static GameOptionsData GameOptions = new GameOptionsData();
+
+ public List<PlayerTask> myTasks = new List<PlayerTask>();
+
+ [NonSerialized]
+ public uint TaskIdCount;
+
+ public SpriteAnim[] ScannerAnims;
+
+ public SpriteRenderer[] ScannersImages;
+
+ public AudioClip[] VentMoveSounds;
+
+ public AudioClip VentEnterSound;
+
+ private IUsable closest;
+
+ private bool isNew = true;
+
+ public float crewStreak;
+
+ public static List<PlayerControl> AllPlayerControls = new List<PlayerControl>();
+
+ private Dictionary<Collider2D, IUsable> cache = new Dictionary<Collider2D, IUsable>(PlayerControl.ColliderComparer.Instance);
+
+ private List<IUsable> itemsInRange = new List<IUsable>();
+
+ private List<IUsable> newItemsInRange = new List<IUsable>();
+
+ private byte scannerCount;
+
+ private int LastStartCounter;
+
+ public class ColliderComparer : IEqualityComparer<Collider2D>
+ {
+ public static readonly PlayerControl.ColliderComparer Instance = new PlayerControl.ColliderComparer();
+
+ public bool Equals(Collider2D x, Collider2D y)
+ {
+ return x == y;
+ }
+
+ public int GetHashCode(Collider2D obj)
+ {
+ return obj.GetInstanceID();
+ }
+ }
+
+ public class UsableComparer : IEqualityComparer<IUsable>
+ {
+ public static readonly PlayerControl.UsableComparer Instance = new PlayerControl.UsableComparer();
+
+ public bool Equals(IUsable x, IUsable y)
+ {
+ return x == y;
+ }
+
+ public int GetHashCode(IUsable obj)
+ {
+ return obj.GetHashCode();
+ }
+ }
+
+ public enum RpcCalls : byte
+ {
+ PlayAnimation,
+ CompleteTask,
+ SyncSettings,
+ SetInfected,
+ Exiled,
+ CheckName,
+ SetName,
+ CheckColor,
+ SetColor,
+ SetHat,
+ SetSkin,
+ ReportDeadBody,
+ MurderPlayer,
+ SendChat,
+ TimesImpostor,
+ StartMeeting,
+ SetScanner,
+ SendChatNote,
+ SetPet,
+ SetStartCounter
+ }
+
+ public void SetKillTimer(float time)
+ {
+ this.killTimer = time;
+ if (PlayerControl.GameOptions.KillCooldown > 0f)
+ {
+ DestroyableSingleton<HudManager>.Instance.KillButton.SetCoolDown(this.killTimer, PlayerControl.GameOptions.KillCooldown);
+ return;
+ }
+ DestroyableSingleton<HudManager>.Instance.KillButton.SetCoolDown(0f, PlayerControl.GameOptions.KillCooldown);
+ }
+
+ private void Awake()
+ {
+ this.myRend = base.GetComponent<SpriteRenderer>();
+ this.MyPhysics = base.GetComponent<PlayerPhysics>();
+ this.NetTransform = base.GetComponent<CustomNetworkTransform>();
+ this.Collider = base.GetComponent<Collider2D>();
+ PlayerControl.AllPlayerControls.Add(this);
+ }
+
+ private void Start()
+ {
+ this.RemainingEmergencies = PlayerControl.GameOptions.NumEmergencyMeetings;
+ if (base.AmOwner)
+ {
+ this.myLight = UnityEngine.Object.Instantiate<LightSource>(this.LightPrefab);
+ this.myLight.transform.SetParent(base.transform);
+ this.myLight.transform.localPosition = this.Collider.offset;
+ PlayerControl.LocalPlayer = this;
+ Camera.main.GetComponent<FollowerCamera>().SetTarget(this);
+ this.SetName(SaveManager.PlayerName);
+ this.SetColor(SaveManager.BodyColor);
+ this.CmdCheckName(SaveManager.PlayerName);
+ this.CmdCheckColor(SaveManager.BodyColor);
+ this.RpcSetPet(SaveManager.LastPet);
+ this.RpcSetHat(SaveManager.LastHat);
+ this.RpcSetSkin(SaveManager.LastSkin);
+ this.RpcSetTimesImpostor(StatsManager.Instance.CrewmateStreak);
+ }
+ else
+ {
+ base.StartCoroutine(this.ClientInitialize());
+ }
+ if (this.isNew)
+ {
+ this.isNew = false;
+ base.StartCoroutine(this.MyPhysics.CoSpawnPlayer(LobbyBehaviour.Instance));
+ }
+ }
+
+ private IEnumerator ClientInitialize()
+ {
+ this.Visible = false;
+ while (!GameData.Instance)
+ {
+ yield return null;
+ }
+ while (this.Data == null)
+ {
+ yield return null;
+ }
+ while (string.IsNullOrEmpty(this.Data.PlayerName))
+ {
+ yield return null;
+ }
+ this.SetName(this.Data.PlayerName);
+ this.SetColor(this.Data.ColorId);
+ this.SetHat(this.Data.HatId);
+ this.SetSkin(this.Data.SkinId);
+ this.SetPet(this.Data.PetId);
+ this.Visible = true;
+ yield break;
+ }
+
+ public override void OnDestroy()
+ {
+ if (this.CurrentPet)
+ {
+ UnityEngine.Object.Destroy(this.CurrentPet.gameObject);
+ }
+ PlayerControl.AllPlayerControls.Remove(this);
+ base.OnDestroy();
+ }
+
+ private void FixedUpdate()
+ {
+ if (!GameData.Instance)
+ {
+ return;
+ }
+ GameData.PlayerInfo data = this.Data;
+ if (data == null)
+ {
+ return;
+ }
+ if (data.IsDead && PlayerControl.LocalPlayer)
+ {
+ this.Visible = PlayerControl.LocalPlayer.Data.IsDead;
+ }
+ if (base.AmOwner)
+ {
+ if (ShipStatus.Instance)
+ {
+ this.myLight.LightRadius = ShipStatus.Instance.CalculateLightRadius(data);
+ }
+ if (data.IsImpostor && this.CanMove && !data.IsDead)
+ {
+ this.SetKillTimer(Mathf.Max(0f, this.killTimer - Time.fixedDeltaTime));
+ PlayerControl target = this.FindClosestTarget();
+ DestroyableSingleton<HudManager>.Instance.KillButton.SetTarget(target);
+ }
+ else
+ {
+ DestroyableSingleton<HudManager>.Instance.KillButton.SetTarget(null);
+ }
+ if (this.CanMove || this.inVent)
+ {
+ this.newItemsInRange.Clear();
+ bool flag = (PlayerControl.GameOptions.GhostsDoTasks || !data.IsDead) && (!AmongUsClient.Instance || !AmongUsClient.Instance.IsGameOver) && this.CanMove;
+ Vector2 truePosition = this.GetTruePosition();
+ int num = Physics2D.OverlapCircleNonAlloc(truePosition, this.MaxReportDistance, this.hitBuffer, Constants.Usables);
+ IUsable usable = null;
+ float num2 = float.MaxValue;
+ bool flag2 = false;
+ for (int i = 0; i < num; i++)
+ {
+ Collider2D collider2D = this.hitBuffer[i];
+ IUsable usable2;
+ if (!this.cache.TryGetValue(collider2D, out usable2))
+ {
+ usable2 = (this.cache[collider2D] = collider2D.GetComponent<IUsable>());
+ }
+ if (usable2 != null && (flag || this.inVent))
+ {
+ bool flag3;
+ bool flag4;
+ float num3 = usable2.CanUse(data, out flag3, out flag4);
+ if (flag3 || flag4)
+ {
+ this.newItemsInRange.Add(usable2);
+ }
+ if (flag3 && num3 < num2)
+ {
+ num2 = num3;
+ usable = usable2;
+ }
+ }
+ if (flag && !data.IsDead && !flag2 && collider2D.tag == "DeadBody")
+ {
+ DeadBody component = collider2D.GetComponent<DeadBody>();
+ if (!PhysicsHelpers.AnythingBetween(truePosition, component.TruePosition, Constants.ShipAndObjectsMask, false))
+ {
+ flag2 = true;
+ }
+ }
+ }
+ for (int l = this.itemsInRange.Count - 1; l > -1; l--)
+ {
+ IUsable item = this.itemsInRange[l];
+ int num4 = this.newItemsInRange.FindIndex((IUsable j) => j == item);
+ if (num4 == -1)
+ {
+ item.SetOutline(false, false);
+ this.itemsInRange.RemoveAt(l);
+ }
+ else
+ {
+ this.newItemsInRange.RemoveAt(num4);
+ item.SetOutline(true, usable == item);
+ }
+ }
+ for (int k = 0; k < this.newItemsInRange.Count; k++)
+ {
+ IUsable usable3 = this.newItemsInRange[k];
+ usable3.SetOutline(true, usable == usable3);
+ this.itemsInRange.Add(usable3);
+ }
+ this.closest = usable;
+ DestroyableSingleton<HudManager>.Instance.UseButton.SetTarget(usable);
+ DestroyableSingleton<HudManager>.Instance.ReportButton.SetActive(flag2);
+ return;
+ }
+ this.closest = null;
+ DestroyableSingleton<HudManager>.Instance.UseButton.SetTarget(null);
+ DestroyableSingleton<HudManager>.Instance.ReportButton.SetActive(false);
+ }
+ }
+
+ public void UseClosest()
+ {
+ if (this.closest != null)
+ {
+ this.closest.Use();
+ }
+ this.closest = null;
+ DestroyableSingleton<HudManager>.Instance.UseButton.SetTarget(null);
+ }
+
+ public void ReportClosest()
+ {
+ if (AmongUsClient.Instance.IsGameOver)
+ {
+ return;
+ }
+ if (PlayerControl.LocalPlayer.Data.IsDead)
+ {
+ return;
+ }
+ foreach (Collider2D collider2D in Physics2D.OverlapCircleAll(base.transform.position, this.MaxReportDistance, Constants.NotShipMask))
+ {
+ if (!(collider2D.tag != "DeadBody"))
+ {
+ DeadBody component = collider2D.GetComponent<DeadBody>();
+ if (component && !component.Reported)
+ {
+ component.OnClick();
+ if (component.Reported)
+ {
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ public void PlayStepSound()
+ {
+ if (!Constants.ShouldPlaySfx())
+ {
+ return;
+ }
+ if (DestroyableSingleton<HudManager>.InstanceExists && PlayerControl.LocalPlayer == this)
+ {
+ ShipRoom lastRoom = DestroyableSingleton<HudManager>.Instance.roomTracker.LastRoom;
+ if (lastRoom && lastRoom.FootStepSounds)
+ {
+ AudioClip clip = lastRoom.FootStepSounds.Random();
+ this.FootSteps.clip = clip;
+ this.FootSteps.Play();
+ }
+ }
+ }
+
+ private void SetScanner(bool on, byte cnt)
+ {
+ if (cnt < this.scannerCount)
+ {
+ return;
+ }
+ this.scannerCount = cnt;
+ for (int i = 0; i < this.ScannerAnims.Length; i++)
+ {
+ SpriteAnim spriteAnim = this.ScannerAnims[i];
+ if (on && !this.Data.IsDead)
+ {
+ spriteAnim.gameObject.SetActive(true);
+ spriteAnim.Play(null, 1f);
+ this.ScannersImages[i].flipX = !this.myRend.flipX;
+ }
+ else
+ {
+ if (spriteAnim.isActiveAndEnabled)
+ {
+ spriteAnim.Stop();
+ }
+ spriteAnim.gameObject.SetActive(false);
+ }
+ }
+ }
+
+ public Vector2 GetTruePosition()
+ {
+ return base.transform.position + this.Collider.offset;
+ }
+
+ private PlayerControl FindClosestTarget()
+ {
+ PlayerControl result = null;
+ float num = GameOptionsData.KillDistances[Mathf.Clamp(PlayerControl.GameOptions.KillDistance, 0, 2)];
+ if (!ShipStatus.Instance)
+ {
+ return null;
+ }
+ Vector2 truePosition = this.GetTruePosition();
+ List<GameData.PlayerInfo> allPlayers = GameData.Instance.AllPlayers;
+ for (int i = 0; i < allPlayers.Count; i++)
+ {
+ GameData.PlayerInfo playerInfo = allPlayers[i];
+ if (!playerInfo.Disconnected && playerInfo.PlayerId != this.PlayerId && !playerInfo.IsDead && !playerInfo.IsImpostor)
+ {
+ PlayerControl @object = playerInfo.Object;
+ if (@object)
+ {
+ Vector2 vector = @object.GetTruePosition() - truePosition;
+ float magnitude = vector.magnitude;
+ if (magnitude <= num && !PhysicsHelpers.AnyNonTriggersBetween(truePosition, vector.normalized, magnitude, Constants.ShipAndObjectsMask))
+ {
+ result = @object;
+ num = magnitude;
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ public void SetTasks(byte[] tasks)
+ {
+ base.StartCoroutine(this.CoSetTasks(tasks));
+ }
+
+ private IEnumerator CoSetTasks(byte[] tasks)
+ {
+ while (!ShipStatus.Instance)
+ {
+ yield return null;
+ }
+ if (base.AmOwner)
+ {
+ DestroyableSingleton<HudManager>.Instance.TaskStuff.SetActive(true);
+ StatsManager instance = StatsManager.Instance;
+ uint num = instance.GamesStarted;
+ instance.GamesStarted = num + 1U;
+ if (this.Data.IsImpostor)
+ {
+ StatsManager instance2 = StatsManager.Instance;
+ num = instance2.TimesImpostor;
+ instance2.TimesImpostor = num + 1U;
+ StatsManager.Instance.CrewmateStreak = 0U;
+ }
+ else
+ {
+ StatsManager instance3 = StatsManager.Instance;
+ num = instance3.TimesCrewmate;
+ instance3.TimesCrewmate = num + 1U;
+ StatsManager instance4 = StatsManager.Instance;
+ num = instance4.CrewmateStreak;
+ instance4.CrewmateStreak = num + 1U;
+ DestroyableSingleton<HudManager>.Instance.KillButton.gameObject.SetActive(false);
+ }
+ DestroyableSingleton<Telemetry>.Instance.StartGame(SaveManager.SendName, AmongUsClient.Instance.AmHost, GameData.Instance.PlayerCount, PlayerControl.GameOptions.NumImpostors, AmongUsClient.Instance.GameMode, StatsManager.Instance.TimesImpostor, StatsManager.Instance.GamesStarted, StatsManager.Instance.CrewmateStreak);
+ }
+ foreach (byte idx in tasks)
+ {
+ NormalPlayerTask normalPlayerTask = UnityEngine.Object.Instantiate<NormalPlayerTask>(ShipStatus.Instance.GetTaskById(idx), base.transform);
+ PlayerTask playerTask = normalPlayerTask;
+ uint num = this.TaskIdCount;
+ this.TaskIdCount = num + 1U;
+ playerTask.Id = num;
+ normalPlayerTask.Owner = this;
+ normalPlayerTask.Initialize();
+ this.myTasks.Add(normalPlayerTask);
+ }
+ yield break;
+ }
+
+ public void AddSystemTask(SystemTypes system)
+ {
+ PlayerTask original;
+ if (system <= SystemTypes.Electrical)
+ {
+ if (system != SystemTypes.Reactor)
+ {
+ if (system != SystemTypes.Electrical)
+ {
+ return;
+ }
+ original = ShipStatus.Instance.SpecialTasks[1];
+ }
+ else
+ {
+ original = ShipStatus.Instance.SpecialTasks[0];
+ }
+ }
+ else if (system != SystemTypes.LifeSupp)
+ {
+ if (system != SystemTypes.Comms)
+ {
+ return;
+ }
+ original = ShipStatus.Instance.SpecialTasks[2];
+ }
+ else
+ {
+ original = ShipStatus.Instance.SpecialTasks[3];
+ }
+ PlayerControl localPlayer = PlayerControl.LocalPlayer;
+ PlayerTask playerTask = UnityEngine.Object.Instantiate<PlayerTask>(original, localPlayer.transform);
+ PlayerTask playerTask2 = playerTask;
+ PlayerControl playerControl = localPlayer;
+ uint taskIdCount = playerControl.TaskIdCount;
+ playerControl.TaskIdCount = taskIdCount + 1U;
+ playerTask2.Id = (uint)((byte)taskIdCount);
+ playerTask.Owner = localPlayer;
+ playerTask.Initialize();
+ localPlayer.myTasks.Add(playerTask);
+ }
+
+ public void RemoveTask(PlayerTask task)
+ {
+ task.OnRemove();
+ this.myTasks.Remove(task);
+ GameData.Instance.TutOnlyRemoveTask(this.PlayerId, task.Id);
+ DestroyableSingleton<HudManager>.Instance.UseButton.SetTarget(null);
+ UnityEngine.Object.Destroy(task.gameObject);
+ }
+
+ private void ClearTasks()
+ {
+ for (int i = 0; i < this.myTasks.Count; i++)
+ {
+ PlayerTask playerTask = this.myTasks[i];
+ playerTask.OnRemove();
+ UnityEngine.Object.Destroy(playerTask.gameObject);
+ }
+ this.myTasks.Clear();
+ }
+
+ public void RemoveInfected()
+ {
+ GameData.PlayerInfo playerById = GameData.Instance.GetPlayerById(this.PlayerId);
+ if (playerById.IsImpostor)
+ {
+ playerById.Object.nameText.Color = Color.white;
+ playerById.IsImpostor = false;
+ this.myTasks.RemoveAt(0);
+ DestroyableSingleton<HudManager>.Instance.KillButton.gameObject.SetActive(false);
+ }
+ }
+
+ public void Die(DeathReason reason)
+ {
+ if (!DestroyableSingleton<TutorialManager>.InstanceExists)
+ {
+ StatsManager.Instance.LastGameStarted = DateTime.MinValue;
+ StatsManager instance = StatsManager.Instance;
+ float banPoints = instance.BanPoints;
+ instance.BanPoints = banPoints - 1f;
+ }
+ TempData.LastDeathReason = reason;
+ if (this.CurrentPet)
+ {
+ this.CurrentPet.SetMourning();
+ }
+ this.Data.IsDead = true;
+ base.gameObject.layer = LayerMask.NameToLayer("Ghost");
+ this.nameText.GetComponent<MeshRenderer>().material.SetInt("_Mask", 0);
+ if (base.AmOwner)
+ {
+ DestroyableSingleton<HudManager>.Instance.Chat.SetVisible(true);
+ }
+ }
+
+ public void Revive()
+ {
+ this.Data.IsDead = false;
+ base.gameObject.layer = LayerMask.NameToLayer("Players");
+ this.MyPhysics.ResetAnim(true);
+ if (this.CurrentPet)
+ {
+ this.CurrentPet.Source = this;
+ }
+ this.nameText.GetComponent<MeshRenderer>().material.SetInt("_Mask", 4);
+ if (base.AmOwner)
+ {
+ DestroyableSingleton<HudManager>.Instance.KillButton.gameObject.SetActive(this.Data.IsImpostor);
+ DestroyableSingleton<HudManager>.Instance.Chat.ForceClosed();
+ DestroyableSingleton<HudManager>.Instance.Chat.SetVisible(false);
+ }
+ }
+
+ public void PlayAnimation(byte animType)
+ {
+ if (animType == 1)
+ {
+ ShipStatus.Instance.StartShields();
+ return;
+ }
+ if (animType == 6)
+ {
+ ShipStatus.Instance.FireWeapon();
+ return;
+ }
+ if (animType - 9 > 1)
+ {
+ return;
+ }
+ ShipStatus.Instance.OpenHatch();
+ }
+
+ public void CompleteTask(uint idx)
+ {
+ PlayerTask playerTask = this.myTasks.Find((PlayerTask p) => p.Id == idx);
+ if (playerTask)
+ {
+ GameData.Instance.CompleteTask(this, idx);
+ playerTask.Complete();
+ DestroyableSingleton<Telemetry>.Instance.WriteCompleteTask(this.PlayerId, playerTask.TaskType);
+ return;
+ }
+ Debug.LogWarning(this.PlayerId + ": Server didn't have task: " + idx);
+ }
+
+ public void SetInfected(byte[] infected)
+ {
+ if (!GameData.Instance)
+ {
+ Debug.Log("No game data instance.");
+ }
+ StatsManager instance = StatsManager.Instance;
+ float banPoints = instance.BanPoints;
+ instance.BanPoints = banPoints + 1f;
+ StatsManager.Instance.LastGameStarted = DateTime.UtcNow;
+ for (int i = 0; i < infected.Length; i++)
+ {
+ GameData.PlayerInfo playerById = GameData.Instance.GetPlayerById(infected[i]);
+ if (playerById != null)
+ {
+ playerById.IsImpostor = true;
+ }
+ else
+ {
+ Debug.LogError("Couldn't set impostor: " + infected[i]);
+ }
+ }
+ DestroyableSingleton<HudManager>.Instance.MapButton.gameObject.SetActive(true);
+ DestroyableSingleton<HudManager>.Instance.ReportButton.gameObject.SetActive(true);
+ PlayerControl.LocalPlayer.RemainingEmergencies = PlayerControl.GameOptions.NumEmergencyMeetings;
+ GameData.PlayerInfo data = PlayerControl.LocalPlayer.Data;
+ if (data.IsImpostor)
+ {
+ ImportantTextTask importantTextTask = new GameObject("_Player").AddComponent<ImportantTextTask>();
+ importantTextTask.transform.SetParent(PlayerControl.LocalPlayer.transform, false);
+ importantTextTask.Text = DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.ImpostorTask, Array.Empty<object>()) + "\r\n[FFFFFFFF]" + DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.FakeTasks, Array.Empty<object>());
+ this.myTasks.Insert(0, importantTextTask);
+ DestroyableSingleton<HudManager>.Instance.KillButton.gameObject.SetActive(true);
+ PlayerControl.LocalPlayer.SetKillTimer(10f);
+ for (int j = 0; j < infected.Length; j++)
+ {
+ GameData.PlayerInfo playerById2 = GameData.Instance.GetPlayerById(infected[j]);
+ if (playerById2 != null)
+ {
+ playerById2.Object.nameText.Color = Palette.ImpostorRed;
+ }
+ }
+ }
+ if (!DestroyableSingleton<TutorialManager>.InstanceExists)
+ {
+ List<PlayerControl> yourTeam;
+ if (data.IsImpostor)
+ {
+ yourTeam = (from pcd in GameData.Instance.AllPlayers
+ where !pcd.Disconnected
+ where pcd.IsImpostor
+ select pcd.Object).OrderBy(delegate(PlayerControl pc)
+ {
+ if (!(pc == PlayerControl.LocalPlayer))
+ {
+ return 1;
+ }
+ return 0;
+ }).ToList<PlayerControl>();
+ }
+ else
+ {
+ yourTeam = (from pcd in GameData.Instance.AllPlayers
+ where !pcd.Disconnected
+ select pcd.Object).OrderBy(delegate(PlayerControl pc)
+ {
+ if (!(pc == PlayerControl.LocalPlayer))
+ {
+ return 1;
+ }
+ return 0;
+ }).ToList<PlayerControl>();
+ }
+ base.StopAllCoroutines();
+ DestroyableSingleton<HudManager>.Instance.StartCoroutine(DestroyableSingleton<HudManager>.Instance.CoShowIntro(yourTeam));
+ }
+ }
+
+ public void Exiled()
+ {
+ this.Die(DeathReason.Exile);
+ if (base.AmOwner)
+ {
+ StatsManager instance = StatsManager.Instance;
+ uint timesEjected = instance.TimesEjected;
+ instance.TimesEjected = timesEjected + 1U;
+ DestroyableSingleton<HudManager>.Instance.ShadowQuad.gameObject.SetActive(false);
+ ImportantTextTask importantTextTask = new GameObject("_Player").AddComponent<ImportantTextTask>();
+ importantTextTask.transform.SetParent(base.transform, false);
+ if (this.Data.IsImpostor)
+ {
+ this.ClearTasks();
+ importantTextTask.Text = DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.GhostImpostor, Array.Empty<object>());
+ }
+ else if (!PlayerControl.GameOptions.GhostsDoTasks)
+ {
+ this.ClearTasks();
+ importantTextTask.Text = DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.GhostIgnoreTasks, Array.Empty<object>());
+ }
+ else
+ {
+ importantTextTask.Text = DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.GhostDoTasks, Array.Empty<object>());
+ }
+ this.myTasks.Insert(0, importantTextTask);
+ }
+ }
+
+ public void CheckName(string name)
+ {
+ List<GameData.PlayerInfo> allPlayers = GameData.Instance.AllPlayers;
+ bool flag = allPlayers.Any((GameData.PlayerInfo i) => i.PlayerId != this.PlayerId && i.PlayerName.Equals(name, StringComparison.OrdinalIgnoreCase));
+ if (flag)
+ {
+ for (int k = 1; k < 100; k++)
+ {
+ string text = name + " " + k;
+ flag = false;
+ for (int j = 0; j < allPlayers.Count; j++)
+ {
+ if (allPlayers[j].PlayerId != this.PlayerId && allPlayers[j].PlayerName.Equals(text, StringComparison.OrdinalIgnoreCase))
+ {
+ flag = true;
+ break;
+ }
+ }
+ if (!flag)
+ {
+ name = text;
+ break;
+ }
+ }
+ }
+ this.RpcSetName(name);
+ GameData.Instance.UpdateName(this.PlayerId, name);
+ }
+
+ public void SetName(string name)
+ {
+ if (GameData.Instance)
+ {
+ GameData.Instance.UpdateName(this.PlayerId, name);
+ }
+ base.gameObject.name = name;
+ this.nameText.Text = name;
+ this.nameText.GetComponent<MeshRenderer>().material.SetInt("_Mask", 4);
+ }
+
+ public void CheckColor(byte bodyColor)
+ {
+ List<GameData.PlayerInfo> allPlayers = GameData.Instance.AllPlayers;
+ int num = 0;
+ while (num++ < 100 && allPlayers.Any((GameData.PlayerInfo p) => !p.Disconnected && p.PlayerId != this.PlayerId && p.ColorId == bodyColor))
+ {
+ bodyColor = (byte)((int)(bodyColor + 1) % Palette.PlayerColors.Length);
+ }
+ this.RpcSetColor(bodyColor);
+ }
+
+ public void SetHatAlpha(float a)
+ {
+ Color white = Color.white;
+ white.a = a;
+ this.HatRenderer.color = white;
+ }
+
+ public void SetColor(byte bodyColor)
+ {
+ if (GameData.Instance)
+ {
+ GameData.Instance.UpdateColor(this.PlayerId, bodyColor);
+ }
+ if (this.myRend == null)
+ {
+ base.GetComponent<SpriteRenderer>();
+ }
+ PlayerControl.SetPlayerMaterialColors((int)bodyColor, this.myRend);
+ if (this.CurrentPet)
+ {
+ PlayerControl.SetPlayerMaterialColors((int)bodyColor, this.CurrentPet.rend);
+ }
+ }
+
+ public void SetSkin(uint skinId)
+ {
+ if (GameData.Instance)
+ {
+ GameData.Instance.UpdateSkin(this.PlayerId, skinId);
+ }
+ this.MyPhysics.SetSkin(skinId);
+ }
+
+ public void SetHat(uint hatId)
+ {
+ if (GameData.Instance)
+ {
+ GameData.Instance.UpdateHat(this.PlayerId, hatId);
+ }
+ PlayerControl.SetHatImage(hatId, this.HatRenderer);
+ this.nameText.transform.localPosition = new Vector3(0f, (hatId == 0U) ? 0.7f : 1.05f, -0.5f);
+ }
+
+ public void SetPet(uint petId)
+ {
+ if (this.CurrentPet)
+ {
+ UnityEngine.Object.Destroy(this.CurrentPet.gameObject);
+ }
+ this.CurrentPet = UnityEngine.Object.Instantiate<PetBehaviour>(DestroyableSingleton<HatManager>.Instance.GetPetById(petId));
+ this.CurrentPet.transform.position = base.transform.position;
+ this.CurrentPet.Source = this;
+ GameData.PlayerInfo data = this.Data;
+ if (this.Data != null)
+ {
+ GameData.Instance.UpdatePet(this.PlayerId, petId);
+ this.Data.PetId = petId;
+ PlayerControl.SetPlayerMaterialColors((int)this.Data.ColorId, this.CurrentPet.rend);
+ }
+ }
+
+ public static void SetPetImage(uint petId, int colorId, SpriteRenderer target)
+ {
+ if (!DestroyableSingleton<HatManager>.InstanceExists)
+ {
+ return;
+ }
+ PlayerControl.SetPetImage(DestroyableSingleton<HatManager>.Instance.GetPetById(petId), colorId, target);
+ }
+
+ public static void SetPetImage(PetBehaviour pet, int colorId, SpriteRenderer target)
+ {
+ target.sprite = pet.rend.sprite;
+ if (target != pet.rend)
+ {
+ target.material = new Material(pet.rend.sharedMaterial);
+ PlayerControl.SetPlayerMaterialColors(colorId, target);
+ }
+ }
+
+ public static void SetSkinImage(uint skinId, SpriteRenderer target)
+ {
+ if (!DestroyableSingleton<HatManager>.InstanceExists)
+ {
+ return;
+ }
+ PlayerControl.SetSkinImage(DestroyableSingleton<HatManager>.Instance.GetSkinById(skinId), target);
+ }
+
+ public static void SetSkinImage(SkinData skin, SpriteRenderer target)
+ {
+ target.sprite = skin.IdleFrame;
+ }
+
+ public static void SetHatImage(uint hatId, SpriteRenderer target)
+ {
+ if (!DestroyableSingleton<HatManager>.InstanceExists)
+ {
+ return;
+ }
+ PlayerControl.SetHatImage(DestroyableSingleton<HatManager>.Instance.GetHatById(hatId), target);
+ }
+
+ public static void SetHatImage(HatBehaviour hat, SpriteRenderer target)
+ {
+ if (!target)
+ {
+ return;
+ }
+ if (hat)
+ {
+ target.sprite = hat.MainImage;
+ Vector3 localPosition = target.transform.localPosition;
+ localPosition.z = (hat.InFront ? -0.0001f : 0.0001f);
+ target.transform.localPosition = localPosition;
+ return;
+ }
+ string str = (!hat) ? "null" : hat.name;
+ Debug.LogError("Player: " + target.name + "\tHat: " + str);
+ }
+
+ private void ReportDeadBody(GameData.PlayerInfo target)
+ {
+ if (AmongUsClient.Instance.IsGameOver)
+ {
+ return;
+ }
+ if (MeetingHud.Instance)
+ {
+ return;
+ }
+ if (target == null && PlayerControl.LocalPlayer.myTasks.Any(new Func<PlayerTask, bool>(PlayerTask.TaskIsEmergency)))
+ {
+ return;
+ }
+ if (this.Data.IsDead)
+ {
+ return;
+ }
+ MeetingRoomManager.Instance.AssignSelf(this, target);
+ if (!AmongUsClient.Instance.AmHost)
+ {
+ return;
+ }
+ if (ShipStatus.Instance.CheckTaskCompletion())
+ {
+ return;
+ }
+ DestroyableSingleton<HudManager>.Instance.OpenMeetingRoom(this);
+ this.RpcStartMeeting(target);
+ }
+
+ public IEnumerator CoStartMeeting(GameData.PlayerInfo target)
+ {
+ DestroyableSingleton<Telemetry>.Instance.WriteMeetingStarted(target == null);
+ while (!MeetingHud.Instance)
+ {
+ yield return null;
+ }
+ MeetingRoomManager.Instance.RemoveSelf();
+ DeadBody[] array = UnityEngine.Object.FindObjectsOfType<DeadBody>();
+ for (int i = 0; i < array.Length; i++)
+ {
+ UnityEngine.Object.Destroy(array[i].gameObject);
+ }
+ for (int j = 0; j < PlayerControl.AllPlayerControls.Count; j++)
+ {
+ PlayerControl playerControl = PlayerControl.AllPlayerControls[j];
+ if (!playerControl.GetComponent<DummyBehaviour>().enabled)
+ {
+ playerControl.MyPhysics.ExitAllVents();
+ playerControl.NetTransform.SnapTo(ShipStatus.Instance.GetSpawnLocation((int)playerControl.PlayerId, GameData.Instance.PlayerCount));
+ }
+ }
+ if (base.AmOwner)
+ {
+ if (target != null)
+ {
+ StatsManager instance = StatsManager.Instance;
+ uint num = instance.BodiesReported;
+ instance.BodiesReported = num + 1U;
+ }
+ else
+ {
+ this.RemainingEmergencies--;
+ StatsManager instance2 = StatsManager.Instance;
+ uint num = instance2.EmergenciesCalled;
+ instance2.EmergenciesCalled = num + 1U;
+ }
+ }
+ if (MapBehaviour.Instance)
+ {
+ MapBehaviour.Instance.Close();
+ }
+ if (Minigame.Instance)
+ {
+ Minigame.Instance.Close();
+ }
+ KillAnimation.SetMovement(this, true);
+ MeetingHud.Instance.StartCoroutine(MeetingHud.Instance.CoIntro(this, target));
+ yield break;
+ }
+
+ public void MurderPlayer(PlayerControl target)
+ {
+ if (AmongUsClient.Instance.IsGameOver)
+ {
+ return;
+ }
+ if (!target || this.Data.IsDead || !this.Data.IsImpostor || this.Data.Disconnected)
+ {
+ Debug.LogWarning(string.Format("Bad kill from {0} to {1}", this.PlayerId, ((int)((target != null) ? new byte?(target.PlayerId) : null)) ?? -1));
+ return;
+ }
+ GameData.PlayerInfo data = target.Data;
+ if (data != null && !data.IsDead)
+ {
+ if (base.AmOwner)
+ {
+ StatsManager instance = StatsManager.Instance;
+ uint num = instance.ImpostorKills;
+ instance.ImpostorKills = num + 1U;
+ if (Constants.ShouldPlaySfx())
+ {
+ SoundManager.Instance.PlaySound(PlayerControl.LocalPlayer.KillSfx, false, 0.8f);
+ }
+ }
+ this.SetKillTimer(PlayerControl.GameOptions.KillCooldown);
+ DestroyableSingleton<Telemetry>.Instance.WriteMurder(this.PlayerId, target.PlayerId, target.transform.position);
+ target.gameObject.layer = LayerMask.NameToLayer("Ghost");
+ if (target.AmOwner)
+ {
+ StatsManager instance2 = StatsManager.Instance;
+ uint num = instance2.TimesMurdered;
+ instance2.TimesMurdered = num + 1U;
+ if (Minigame.Instance)
+ {
+ Minigame.Instance.Close();
+ Minigame.Instance.Close();
+ }
+ DestroyableSingleton<HudManager>.Instance.ShadowQuad.gameObject.SetActive(false);
+ target.nameText.GetComponent<MeshRenderer>().material.SetInt("_Mask", 0);
+ DestroyableSingleton<HudManager>.Instance.KillOverlay.ShowOne(this, data);
+ target.RpcSetScanner(false);
+ ImportantTextTask importantTextTask = new GameObject("_Player").AddComponent<ImportantTextTask>();
+ importantTextTask.transform.SetParent(base.transform, false);
+ if (!PlayerControl.GameOptions.GhostsDoTasks)
+ {
+ target.ClearTasks();
+ importantTextTask.Text = DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.GhostIgnoreTasks, Array.Empty<object>());
+ }
+ else
+ {
+ importantTextTask.Text = DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.GhostDoTasks, Array.Empty<object>());
+ }
+ target.myTasks.Insert(0, importantTextTask);
+ }
+ this.MyPhysics.StartCoroutine(this.KillAnimations.Random<KillAnimation>().CoPerformKill(this, target));
+ }
+ }
+
+ public override bool Serialize(MessageWriter writer, bool initialState)
+ {
+ if (initialState)
+ {
+ writer.Write(this.isNew);
+ }
+ writer.Write(this.PlayerId);
+ return true;
+ }
+
+ public override void Deserialize(MessageReader reader, bool initialState)
+ {
+ if (initialState)
+ {
+ this.isNew = reader.ReadBoolean();
+ }
+ this.PlayerId = reader.ReadByte();
+ }
+
+ public void SetPlayerMaterialColors(Renderer rend)
+ {
+ GameData.PlayerInfo playerById = GameData.Instance.GetPlayerById(this.PlayerId);
+ PlayerControl.SetPlayerMaterialColors((int)((playerById != null) ? playerById.ColorId : 0), rend);
+ }
+
+ public static void SetPlayerMaterialColors(int colorId, Renderer rend)
+ {
+ if (!rend)
+ {
+ return;
+ }
+ rend.material.SetColor("_BackColor", Palette.ShadowColors[colorId]);
+ rend.material.SetColor("_BodyColor", Palette.PlayerColors[colorId]);
+ rend.material.SetColor("_VisorColor", Palette.VisorColor);
+ }
+
+ public void RpcSetScanner(bool value)
+ {
+ byte b = this.scannerCount + 1;
+ this.scannerCount = b;
+ byte b2 = b;
+ if (AmongUsClient.Instance.AmClient)
+ {
+ this.SetScanner(value, b2);
+ }
+ MessageWriter messageWriter = AmongUsClient.Instance.StartRpc(this.NetId, 16, SendOption.Reliable);
+ messageWriter.Write(value);
+ messageWriter.Write(b2);
+ messageWriter.EndMessage();
+ }
+
+ public void RpcPlayAnimation(byte animType)
+ {
+ if (AmongUsClient.Instance.AmClient)
+ {
+ this.PlayAnimation(animType);
+ }
+ MessageWriter messageWriter = AmongUsClient.Instance.StartRpc(this.NetId, 0, SendOption.None);
+ messageWriter.Write(animType);
+ messageWriter.EndMessage();
+ }
+
+ public void RpcSetStartCounter(int secondsLeft)
+ {
+ int lastStartCounter = this.LastStartCounter;
+ this.LastStartCounter = lastStartCounter + 1;
+ int value = lastStartCounter;
+ MessageWriter messageWriter = AmongUsClient.Instance.StartRpc(this.NetId, 19, SendOption.Reliable);
+ messageWriter.WritePacked(value);
+ messageWriter.Write((sbyte)secondsLeft);
+ messageWriter.EndMessage();
+ }
+
+ public void RpcCompleteTask(uint idx)
+ {
+ if (AmongUsClient.Instance.AmClient)
+ {
+ this.CompleteTask(idx);
+ }
+ MessageWriter messageWriter = AmongUsClient.Instance.StartRpc(this.NetId, 1, SendOption.Reliable);
+ messageWriter.WritePacked(idx);
+ messageWriter.EndMessage();
+ }
+
+ public void RpcSyncSettings(GameOptionsData gameOptions)
+ {
+ if (!AmongUsClient.Instance.AmHost || DestroyableSingleton<TutorialManager>.InstanceExists)
+ {
+ return;
+ }
+ PlayerControl.GameOptions = gameOptions;
+ SaveManager.GameHostOptions = gameOptions;
+ MessageWriter messageWriter = AmongUsClient.Instance.StartRpc(this.NetId, 2, SendOption.Reliable);
+ messageWriter.WriteBytesAndSize(gameOptions.ToBytes());
+ messageWriter.EndMessage();
+ }
+
+ public void RpcSetInfected(GameData.PlayerInfo[] infected)
+ {
+ byte[] array = (from p in infected
+ select p.PlayerId).ToArray<byte>();
+ if (AmongUsClient.Instance.AmClient)
+ {
+ this.SetInfected(array);
+ }
+ MessageWriter messageWriter = AmongUsClient.Instance.StartRpc(this.NetId, 3, SendOption.Reliable);
+ messageWriter.WriteBytesAndSize(array);
+ messageWriter.EndMessage();
+ }
+
+ public void CmdCheckName(string name)
+ {
+ if (AmongUsClient.Instance.AmHost)
+ {
+ this.CheckName(name);
+ return;
+ }
+ MessageWriter messageWriter = AmongUsClient.Instance.StartRpcImmediately(this.NetId, 5, SendOption.Reliable, AmongUsClient.Instance.HostId);
+ messageWriter.Write(name);
+ AmongUsClient.Instance.FinishRpcImmediately(messageWriter);
+ }
+
+ public void RpcSetSkin(uint skinId)
+ {
+ if (AmongUsClient.Instance.AmClient)
+ {
+ this.SetSkin(skinId);
+ }
+ MessageWriter messageWriter = AmongUsClient.Instance.StartRpc(this.NetId, 10, SendOption.Reliable);
+ messageWriter.WritePacked(skinId);
+ messageWriter.EndMessage();
+ }
+
+ public void RpcSetHat(uint hatId)
+ {
+ if (AmongUsClient.Instance.AmClient)
+ {
+ this.SetHat(hatId);
+ }
+ MessageWriter messageWriter = AmongUsClient.Instance.StartRpc(this.NetId, 9, SendOption.Reliable);
+ messageWriter.WritePacked(hatId);
+ messageWriter.EndMessage();
+ }
+
+ public void RpcSetPet(uint petId)
+ {
+ if (AmongUsClient.Instance.AmClient)
+ {
+ this.SetPet(petId);
+ }
+ MessageWriter messageWriter = AmongUsClient.Instance.StartRpc(this.NetId, 18, SendOption.Reliable);
+ messageWriter.WritePacked(petId);
+ messageWriter.EndMessage();
+ }
+
+ public void RpcSetName(string name)
+ {
+ if (AmongUsClient.Instance.AmClient)
+ {
+ this.SetName(name);
+ }
+ MessageWriter messageWriter = AmongUsClient.Instance.StartRpc(this.NetId, 6, SendOption.Reliable);
+ messageWriter.Write(name);
+ messageWriter.EndMessage();
+ }
+
+ public void CmdCheckColor(byte bodyColor)
+ {
+ if (AmongUsClient.Instance.AmHost)
+ {
+ this.CheckColor(bodyColor);
+ return;
+ }
+ MessageWriter messageWriter = AmongUsClient.Instance.StartRpcImmediately(this.NetId, 7, SendOption.Reliable, AmongUsClient.Instance.HostId);
+ messageWriter.Write(bodyColor);
+ AmongUsClient.Instance.FinishRpcImmediately(messageWriter);
+ }
+
+ public void RpcSetColor(byte bodyColor)
+ {
+ if (AmongUsClient.Instance.AmClient)
+ {
+ this.SetColor(bodyColor);
+ }
+ MessageWriter messageWriter = AmongUsClient.Instance.StartRpc(this.NetId, 8, SendOption.Reliable);
+ messageWriter.Write(bodyColor);
+ messageWriter.EndMessage();
+ }
+
+ public void RpcSetTimesImpostor(float percImpostor)
+ {
+ if (AmongUsClient.Instance.AmClient)
+ {
+ this.crewStreak = percImpostor;
+ }
+ MessageWriter messageWriter = AmongUsClient.Instance.StartRpc(this.NetId, 14, SendOption.None);
+ messageWriter.Write(percImpostor);
+ messageWriter.EndMessage();
+ }
+
+ public bool RpcSendChat(string chatText)
+ {
+ if (string.IsNullOrWhiteSpace(chatText))
+ {
+ return false;
+ }
+ if (AmongUsClient.Instance.AmClient && DestroyableSingleton<HudManager>.Instance)
+ {
+ DestroyableSingleton<HudManager>.Instance.Chat.AddChat(this, chatText);
+ }
+ if (chatText.IndexOf("who", StringComparison.OrdinalIgnoreCase) >= 0)
+ {
+ DestroyableSingleton<Telemetry>.Instance.SendWho();
+ }
+ MessageWriter messageWriter = AmongUsClient.Instance.StartRpc(this.NetId, 13, SendOption.Reliable);
+ messageWriter.Write(chatText);
+ messageWriter.EndMessage();
+ return true;
+ }
+
+ public void RpcSendChatNote(byte srcPlayerId, ChatNoteTypes noteType)
+ {
+ if (AmongUsClient.Instance.AmClient)
+ {
+ GameData.PlayerInfo playerById = GameData.Instance.GetPlayerById(srcPlayerId);
+ DestroyableSingleton<HudManager>.Instance.Chat.AddChatNote(playerById, noteType);
+ }
+ MessageWriter messageWriter = AmongUsClient.Instance.StartRpc(this.NetId, 17, SendOption.Reliable);
+ messageWriter.Write(srcPlayerId);
+ messageWriter.Write((byte)noteType);
+ messageWriter.EndMessage();
+ }
+
+ public void CmdReportDeadBody(GameData.PlayerInfo target)
+ {
+ if (AmongUsClient.Instance.AmHost)
+ {
+ this.ReportDeadBody(target);
+ return;
+ }
+ MessageWriter messageWriter = AmongUsClient.Instance.StartRpc(this.NetId, 11, SendOption.Reliable);
+ messageWriter.Write((target != null) ? target.PlayerId : byte.MaxValue);
+ messageWriter.EndMessage();
+ }
+
+ public void RpcStartMeeting(GameData.PlayerInfo info)
+ {
+ if (AmongUsClient.Instance.AmClient)
+ {
+ base.StartCoroutine(this.CoStartMeeting(info));
+ }
+ MessageWriter messageWriter = AmongUsClient.Instance.StartRpcImmediately(this.NetId, 15, SendOption.Reliable, -1);
+ messageWriter.Write((info != null) ? info.PlayerId : byte.MaxValue);
+ AmongUsClient.Instance.FinishRpcImmediately(messageWriter);
+ }
+
+ public void RpcMurderPlayer(PlayerControl target)
+ {
+ if (AmongUsClient.Instance.AmClient)
+ {
+ this.MurderPlayer(target);
+ }
+ MessageWriter messageWriter = AmongUsClient.Instance.StartRpcImmediately(this.NetId, 12, SendOption.Reliable, -1);
+ messageWriter.WriteNetObject(target);
+ AmongUsClient.Instance.FinishRpcImmediately(messageWriter);
+ }
+
+ public override void HandleRpc(byte callId, MessageReader reader)
+ {
+ switch (callId)
+ {
+ case 0:
+ this.PlayAnimation(reader.ReadByte());
+ return;
+ case 1:
+ this.CompleteTask(reader.ReadPackedUInt32());
+ return;
+ case 2:
+ PlayerControl.GameOptions = GameOptionsData.FromBytes(reader.ReadBytesAndSize());
+ return;
+ case 3:
+ this.SetInfected(reader.ReadBytesAndSize());
+ return;
+ case 4:
+ this.Exiled();
+ return;
+ case 5:
+ this.CheckName(reader.ReadString());
+ return;
+ case 6:
+ this.SetName(reader.ReadString());
+ return;
+ case 7:
+ this.CheckColor(reader.ReadByte());
+ return;
+ case 8:
+ this.SetColor(reader.ReadByte());
+ return;
+ case 9:
+ this.SetHat(reader.ReadPackedUInt32());
+ return;
+ case 10:
+ this.SetSkin(reader.ReadPackedUInt32());
+ return;
+ case 11:
+ {
+ GameData.PlayerInfo playerById = GameData.Instance.GetPlayerById(reader.ReadByte());
+ this.ReportDeadBody(playerById);
+ return;
+ }
+ case 12:
+ {
+ PlayerControl target = reader.ReadNetObject<PlayerControl>();
+ this.MurderPlayer(target);
+ return;
+ }
+ case 13:
+ {
+ string chatText = reader.ReadString();
+ if (DestroyableSingleton<HudManager>.Instance)
+ {
+ DestroyableSingleton<HudManager>.Instance.Chat.AddChat(this, chatText);
+ return;
+ }
+ break;
+ }
+ case 14:
+ this.crewStreak = reader.ReadSingle();
+ return;
+ case 15:
+ {
+ GameData.PlayerInfo playerById2 = GameData.Instance.GetPlayerById(reader.ReadByte());
+ base.StartCoroutine(this.CoStartMeeting(playerById2));
+ return;
+ }
+ case 16:
+ this.SetScanner(reader.ReadBoolean(), reader.ReadByte());
+ break;
+ case 17:
+ {
+ GameData.PlayerInfo playerById3 = GameData.Instance.GetPlayerById(reader.ReadByte());
+ DestroyableSingleton<HudManager>.Instance.Chat.AddChatNote(playerById3, (ChatNoteTypes)reader.ReadByte());
+ return;
+ }
+ case 18:
+ this.SetPet(reader.ReadPackedUInt32());
+ return;
+ case 19:
+ {
+ int num = reader.ReadPackedInt32();
+ sbyte startCounter = reader.ReadSByte();
+ if (DestroyableSingleton<GameStartManager>.InstanceExists && this.LastStartCounter < num)
+ {
+ this.LastStartCounter = num;
+ DestroyableSingleton<GameStartManager>.Instance.SetStartCounter(startCounter);
+ return;
+ }
+ break;
+ }
+ default:
+ return;
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/PlayerParticle.cs b/Client/Assembly-CSharp/PlayerParticle.cs
new file mode 100644
index 0000000..41fa495
--- /dev/null
+++ b/Client/Assembly-CSharp/PlayerParticle.cs
@@ -0,0 +1,39 @@
+using System;
+using UnityEngine;
+
+public class PlayerParticle : PoolableBehavior
+{
+ public Camera FollowCamera { get; set; }
+
+ public SpriteRenderer myRend;
+
+ public float maxDistance = 6f;
+
+ public Vector2 velocity;
+
+ public float angularVelocity;
+
+ private Vector3 lastCamera;
+
+ public void Update()
+ {
+ Vector3 vector = base.transform.localPosition;
+ float sqrMagnitude = vector.sqrMagnitude;
+ if (this.FollowCamera)
+ {
+ Vector3 position = this.FollowCamera.transform.position;
+ position.z = 0f;
+ vector += (position - this.lastCamera) * (1f - base.transform.localScale.x);
+ this.lastCamera = position;
+ sqrMagnitude = (vector - position).sqrMagnitude;
+ }
+ if (sqrMagnitude > this.maxDistance * this.maxDistance)
+ {
+ this.OwnerPool.Reclaim(this);
+ return;
+ }
+ vector += this.velocity * Time.deltaTime;
+ base.transform.localPosition = vector;
+ base.transform.Rotate(0f, 0f, Time.deltaTime * this.angularVelocity);
+ }
+}
diff --git a/Client/Assembly-CSharp/PlayerParticleInfo.cs b/Client/Assembly-CSharp/PlayerParticleInfo.cs
new file mode 100644
index 0000000..620b19f
--- /dev/null
+++ b/Client/Assembly-CSharp/PlayerParticleInfo.cs
@@ -0,0 +1,12 @@
+using System;
+using UnityEngine;
+
+[Serializable]
+public class PlayerParticleInfo
+{
+ public Sprite image;
+
+ public FloatRange angularVel;
+
+ public bool alignToVel;
+}
diff --git a/Client/Assembly-CSharp/PlayerParticles.cs b/Client/Assembly-CSharp/PlayerParticles.cs
new file mode 100644
index 0000000..4f7cf4a
--- /dev/null
+++ b/Client/Assembly-CSharp/PlayerParticles.cs
@@ -0,0 +1,73 @@
+using System;
+using UnityEngine;
+
+public class PlayerParticles : MonoBehaviour
+{
+ public PlayerParticleInfo[] Sprites;
+
+ public FloatRange velocity;
+
+ public FloatRange scale;
+
+ public ObjectPoolBehavior pool;
+
+ public float StartRadius;
+
+ public Camera FollowCamera;
+
+ private RandomFill<PlayerParticleInfo> fill;
+
+ public void Start()
+ {
+ this.fill = new RandomFill<PlayerParticleInfo>();
+ this.fill.Set(this.Sprites);
+ int num = 0;
+ while (this.pool.NotInUse > 0)
+ {
+ PlayerParticle playerParticle = this.pool.Get<PlayerParticle>();
+ PlayerControl.SetPlayerMaterialColors(num++, playerParticle.myRend);
+ this.PlacePlayer(playerParticle, true);
+ }
+ }
+
+ public void Update()
+ {
+ while (this.pool.NotInUse > 0)
+ {
+ PlayerParticle part = this.pool.Get<PlayerParticle>();
+ this.PlacePlayer(part, false);
+ }
+ }
+
+ private void PlacePlayer(PlayerParticle part, bool initial)
+ {
+ Vector3 vector = UnityEngine.Random.insideUnitCircle;
+ if (!initial)
+ {
+ vector.Normalize();
+ }
+ vector *= this.StartRadius;
+ float num = this.scale.Next();
+ part.transform.localScale = new Vector3(num, num, num);
+ vector.z = -num * 0.001f;
+ if (this.FollowCamera)
+ {
+ Vector3 position = this.FollowCamera.transform.position;
+ position.z = 0f;
+ vector += position;
+ part.FollowCamera = this.FollowCamera;
+ }
+ part.transform.localPosition = vector;
+ PlayerParticleInfo playerParticleInfo = this.fill.Get();
+ part.myRend.sprite = playerParticleInfo.image;
+ part.myRend.flipX = BoolRange.Next(0.5f);
+ Vector2 vector2 = -vector.normalized;
+ vector2 = vector2.Rotate(FloatRange.Next(-45f, 45f));
+ part.velocity = vector2 * this.velocity.Next();
+ part.angularVelocity = playerParticleInfo.angularVel.Next();
+ if (playerParticleInfo.alignToVel)
+ {
+ part.transform.localEulerAngles = new Vector3(0f, 0f, Vector2.up.AngleSigned(vector2));
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/PlayerPhysics.cs b/Client/Assembly-CSharp/PlayerPhysics.cs
new file mode 100644
index 0000000..c35e21d
--- /dev/null
+++ b/Client/Assembly-CSharp/PlayerPhysics.cs
@@ -0,0 +1,330 @@
+using System;
+using System.Collections;
+using System.Linq;
+using Assets.CoreScripts;
+using Hazel;
+using InnerNet;
+using PowerTools;
+using UnityEngine;
+
+public class PlayerPhysics : InnerNetObject
+{
+ public float TrueSpeed
+ {
+ get
+ {
+ return this.Speed * PlayerControl.GameOptions.PlayerSpeedMod;
+ }
+ }
+
+ public float TrueGhostSpeed
+ {
+ get
+ {
+ return this.GhostSpeed * PlayerControl.GameOptions.PlayerSpeedMod;
+ }
+ }
+
+ public float Speed = 4.5f;
+
+ public float GhostSpeed = 3f;
+
+ [HideInInspector]
+ private Rigidbody2D body;
+
+ [HideInInspector]
+ private SpriteAnim Animator;
+
+ [HideInInspector]
+ private SpriteRenderer rend;
+
+ [HideInInspector]
+ private PlayerControl myPlayer;
+
+ public AnimationClip RunAnim;
+
+ public AnimationClip IdleAnim;
+
+ public AnimationClip GhostIdleAnim;
+
+ public AnimationClip EnterVentAnim;
+
+ public AnimationClip ExitVentAnim;
+
+ public AnimationClip SpawnAnim;
+
+ public SkinLayer Skin;
+
+ private enum RpcCalls
+ {
+ EnterVent,
+ ExitVent
+ }
+
+ public void Awake()
+ {
+ this.body = base.GetComponent<Rigidbody2D>();
+ this.Animator = base.GetComponent<SpriteAnim>();
+ this.rend = base.GetComponent<SpriteRenderer>();
+ this.myPlayer = base.GetComponent<PlayerControl>();
+ }
+
+ private void FixedUpdate()
+ {
+ this.HandleAnimation();
+ if (base.AmOwner && this.myPlayer.CanMove && GameData.Instance)
+ {
+ DestroyableSingleton<Telemetry>.Instance.WritePosition(this.myPlayer.PlayerId, base.transform.position);
+ GameData.PlayerInfo data = this.myPlayer.Data;
+ if (data == null)
+ {
+ return;
+ }
+ bool isDead = data.IsDead;
+ this.body.velocity = DestroyableSingleton<HudManager>.Instance.joystick.Delta * (isDead ? this.TrueGhostSpeed : this.TrueSpeed);
+ }
+ }
+
+ private void LateUpdate()
+ {
+ Vector3 position = base.transform.position;
+ position.z = position.y / 1000f;
+ base.transform.position = position;
+ }
+
+ public Vector3 Vec2ToPosition(Vector2 pos)
+ {
+ return new Vector3(pos.x, pos.y, pos.y / 1000f);
+ }
+
+ public void SetSkin(uint skinId)
+ {
+ this.Skin.SetSkin(skinId);
+ if (this.Animator.IsPlaying(this.SpawnAnim))
+ {
+ this.Skin.SetSpawn(this.Animator.Time);
+ }
+ }
+
+ public void ResetAnim(bool stopCoroutines = true)
+ {
+ if (stopCoroutines)
+ {
+ this.myPlayer.StopAllCoroutines();
+ base.StopAllCoroutines();
+ }
+ base.enabled = true;
+ this.myPlayer.inVent = false;
+ this.myPlayer.Visible = true;
+ GameData.PlayerInfo data = this.myPlayer.Data;
+ if (data == null || !data.IsDead)
+ {
+ this.Skin.SetIdle();
+ this.Animator.Play(this.IdleAnim, 1f);
+ this.myPlayer.Visible = true;
+ this.myPlayer.SetHatAlpha(1f);
+ return;
+ }
+ this.Skin.SetGhost();
+ this.Animator.Play(this.GhostIdleAnim, 1f);
+ this.myPlayer.SetHatAlpha(0.5f);
+ }
+
+ private void HandleAnimation()
+ {
+ if (this.Animator.IsPlaying(this.SpawnAnim))
+ {
+ return;
+ }
+ if (!GameData.Instance)
+ {
+ return;
+ }
+ Vector2 velocity = this.body.velocity;
+ AnimationClip currentAnimation = this.Animator.GetCurrentAnimation();
+ GameData.PlayerInfo data = this.myPlayer.Data;
+ if (data == null)
+ {
+ return;
+ }
+ if (!data.IsDead)
+ {
+ if (velocity.sqrMagnitude >= 0.05f)
+ {
+ if (currentAnimation != this.RunAnim)
+ {
+ this.Animator.Play(this.RunAnim, 1f);
+ this.Skin.SetRun();
+ }
+ if (velocity.x < -0.01f)
+ {
+ this.rend.flipX = true;
+ }
+ else if (velocity.x > 0.01f)
+ {
+ this.rend.flipX = false;
+ }
+ }
+ else if (currentAnimation == this.RunAnim || currentAnimation == this.SpawnAnim || !currentAnimation)
+ {
+ this.Skin.SetIdle();
+ this.Animator.Play(this.IdleAnim, 1f);
+ this.myPlayer.SetHatAlpha(1f);
+ }
+ }
+ else
+ {
+ this.Skin.SetGhost();
+ if (currentAnimation != this.GhostIdleAnim)
+ {
+ this.Animator.Play(this.GhostIdleAnim, 1f);
+ this.myPlayer.SetHatAlpha(0.5f);
+ }
+ if (velocity.x < -0.01f)
+ {
+ this.rend.flipX = true;
+ }
+ else if (velocity.x > 0.01f)
+ {
+ this.rend.flipX = false;
+ }
+ }
+ this.Skin.Flipped = this.rend.flipX;
+ }
+
+ public IEnumerator CoSpawnPlayer(LobbyBehaviour lobby)
+ {
+ if (!lobby)
+ {
+ yield break;
+ }
+ Vector3 spawnPos = this.Vec2ToPosition(lobby.SpawnPositions[(int)this.myPlayer.PlayerId % lobby.SpawnPositions.Length]);
+ this.myPlayer.nameText.gameObject.SetActive(false);
+ this.myPlayer.Collider.enabled = false;
+ KillAnimation.SetMovement(this.myPlayer, false);
+ bool amFlipped = this.myPlayer.PlayerId > 4;
+ this.myPlayer.GetComponent<SpriteRenderer>().flipX = amFlipped;
+ this.myPlayer.transform.position = spawnPos;
+ SoundManager.Instance.PlaySound(lobby.SpawnSound, false, 1f).volume = 0.75f;
+ this.Skin.SetSpawn(0f);
+ this.Skin.Flipped = this.rend.flipX;
+ yield return new WaitForAnimationFinish(this.Animator, this.SpawnAnim);
+ base.transform.position = spawnPos + new Vector3(amFlipped ? -0.3f : 0.3f, -0.24f);
+ this.ResetAnim(false);
+ Vector2 b = (-spawnPos).normalized;
+ yield return this.WalkPlayerTo(spawnPos + b, 0.01f);
+ this.myPlayer.Collider.enabled = true;
+ KillAnimation.SetMovement(this.myPlayer, true);
+ this.myPlayer.nameText.gameObject.SetActive(true);
+ yield break;
+ }
+
+ public void ExitAllVents()
+ {
+ this.ResetAnim(true);
+ this.myPlayer.moveable = true;
+ Vent[] allVents = ShipStatus.Instance.AllVents;
+ for (int i = 0; i < allVents.Length; i++)
+ {
+ allVents[i].SetButtons(false);
+ }
+ }
+
+ private IEnumerator CoEnterVent(int id)
+ {
+ Vent vent = ShipStatus.Instance.AllVents.First((Vent v) => v.Id == id);
+ this.myPlayer.moveable = false;
+ yield return this.WalkPlayerTo(vent.transform.position, 0.01f);
+ vent.EnterVent();
+ this.Skin.SetEnterVent();
+ yield return new WaitForAnimationFinish(this.Animator, this.EnterVentAnim);
+ this.Skin.SetIdle();
+ this.Animator.Play(this.IdleAnim, 1f);
+ this.myPlayer.Visible = false;
+ this.myPlayer.inVent = true;
+ yield break;
+ }
+
+ private IEnumerator CoExitVent(int id)
+ {
+ Vent vent = ShipStatus.Instance.AllVents.First((Vent v) => v.Id == id);
+ this.myPlayer.Visible = true;
+ this.myPlayer.inVent = false;
+ vent.ExitVent();
+ this.Skin.SetExitVent();
+ yield return new WaitForAnimationFinish(this.Animator, this.ExitVentAnim);
+ this.Skin.SetIdle();
+ this.Animator.Play(this.IdleAnim, 1f);
+ this.myPlayer.moveable = true;
+ yield break;
+ }
+
+ // 移动位置
+ public IEnumerator WalkPlayerTo(Vector2 worldPos, float tolerance = 0.01f)
+ {
+ worldPos -= base.GetComponent<CircleCollider2D>().offset;
+ Rigidbody2D body = this.body;
+ do
+ {
+ Vector2 vector2;
+ Vector2 vector = vector2 = worldPos - base.transform.position;
+ if (vector2.sqrMagnitude <= tolerance)
+ {
+ break;
+ }
+ float d = Mathf.Clamp(vector.magnitude * 2f, 0.01f, 1f);
+ body.velocity = vector.normalized * this.Speed * d;
+ yield return null;
+ }
+ while (body.velocity.magnitude >= 0.0001f);
+ body.velocity = Vector2.zero;
+ yield break;
+ }
+
+ public override bool Serialize(MessageWriter writer, bool initialState)
+ {
+ return false;
+ }
+
+ public override void Deserialize(MessageReader reader, bool initialState)
+ {
+ }
+
+ public void RpcEnterVent(int id)
+ {
+ if (AmongUsClient.Instance.AmClient)
+ {
+ base.StartCoroutine(this.CoEnterVent(id));
+ }
+ MessageWriter messageWriter = AmongUsClient.Instance.StartRpc(this.NetId, 0, SendOption.Reliable);
+ messageWriter.WritePacked(id);
+ messageWriter.EndMessage();
+ }
+
+ public void RpcExitVent(int id)
+ {
+ if (AmongUsClient.Instance.AmClient)
+ {
+ base.StartCoroutine(this.CoExitVent(id));
+ }
+ MessageWriter messageWriter = AmongUsClient.Instance.StartRpc(this.NetId, 1, SendOption.Reliable);
+ messageWriter.WritePacked(id);
+ messageWriter.EndMessage();
+ }
+
+ public override void HandleRpc(byte callId, MessageReader reader)
+ {
+ if (callId == 0)
+ {
+ int id = reader.ReadPackedInt32();
+ base.StartCoroutine(this.CoEnterVent(id));
+ return;
+ }
+ if (callId != 1)
+ {
+ return;
+ }
+ int id2 = reader.ReadPackedInt32();
+ base.StartCoroutine(this.CoExitVent(id2));
+ }
+}
diff --git a/Client/Assembly-CSharp/PlayerTab.cs b/Client/Assembly-CSharp/PlayerTab.cs
new file mode 100644
index 0000000..af57c2b
--- /dev/null
+++ b/Client/Assembly-CSharp/PlayerTab.cs
@@ -0,0 +1,100 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class PlayerTab : MonoBehaviour
+{
+ public ColorChip ColorTabPrefab;
+
+ public SpriteRenderer DemoImage;
+
+ public SpriteRenderer HatImage;
+
+ public SpriteRenderer SkinImage;
+
+ public SpriteRenderer PetImage;
+
+ public FloatRange XRange = new FloatRange(1.5f, 3f);
+
+ public FloatRange YRange = new FloatRange(-1f, -3f);
+
+ private HashSet<int> AvailableColors = new HashSet<int>();
+
+ private List<ColorChip> ColorChips = new List<ColorChip>();
+
+ private const int Columns = 3;
+
+ public void OnEnable()
+ {
+ PlayerControl.SetPlayerMaterialColors((int)PlayerControl.LocalPlayer.Data.ColorId, this.DemoImage);
+ PlayerControl.SetHatImage(SaveManager.LastHat, this.HatImage);
+ PlayerControl.SetSkinImage(SaveManager.LastSkin, this.SkinImage);
+ PlayerControl.SetPetImage(SaveManager.LastPet, (int)PlayerControl.LocalPlayer.Data.ColorId, this.PetImage);
+ float num = (float)Palette.PlayerColors.Length / 3f;
+ for (int i = 0; i < Palette.PlayerColors.Length; i++)
+ {
+ float x = this.XRange.Lerp((float)(i % 3) / 2f);
+ float y = this.YRange.Lerp(1f - (float)(i / 3) / num);
+ ColorChip colorChip = UnityEngine.Object.Instantiate<ColorChip>(this.ColorTabPrefab);
+ colorChip.transform.SetParent(base.transform);
+ colorChip.transform.localPosition = new Vector3(x, y, -1f);
+ int j = i;
+ colorChip.Button.OnClick.AddListener(delegate()
+ {
+ this.SelectColor(j);
+ });
+ colorChip.Inner.color = Palette.PlayerColors[i];
+ this.ColorChips.Add(colorChip);
+ }
+ }
+
+ public void OnDisable()
+ {
+ for (int i = 0; i < this.ColorChips.Count; i++)
+ {
+ UnityEngine.Object.Destroy(this.ColorChips[i].gameObject);
+ }
+ this.ColorChips.Clear();
+ }
+
+ public void Update()
+ {
+ this.UpdateAvailableColors();
+ for (int i = 0; i < this.ColorChips.Count; i++)
+ {
+ this.ColorChips[i].InUseForeground.SetActive(!this.AvailableColors.Contains(i));
+ }
+ }
+
+ private void SelectColor(int colorId)
+ {
+ this.UpdateAvailableColors();
+ if (this.AvailableColors.Remove(colorId))
+ {
+ SaveManager.BodyColor = (byte)colorId;
+ if (PlayerControl.LocalPlayer)
+ {
+ PlayerControl.LocalPlayer.CmdCheckColor((byte)colorId);
+ }
+ }
+ }
+
+ public void UpdateAvailableColors()
+ {
+ PlayerControl.SetPlayerMaterialColors((int)PlayerControl.LocalPlayer.Data.ColorId, this.DemoImage);
+ PlayerControl.SetPetImage(SaveManager.LastPet, (int)PlayerControl.LocalPlayer.Data.ColorId, this.PetImage);
+ for (int i = 0; i < Palette.PlayerColors.Length; i++)
+ {
+ this.AvailableColors.Add(i);
+ }
+ if (GameData.Instance)
+ {
+ List<GameData.PlayerInfo> allPlayers = GameData.Instance.AllPlayers;
+ for (int j = 0; j < allPlayers.Count; j++)
+ {
+ GameData.PlayerInfo playerInfo = allPlayers[j];
+ this.AvailableColors.Remove((int)playerInfo.ColorId);
+ }
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/PlayerTask.cs b/Client/Assembly-CSharp/PlayerTask.cs
new file mode 100644
index 0000000..ddccafe
--- /dev/null
+++ b/Client/Assembly-CSharp/PlayerTask.cs
@@ -0,0 +1,137 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using UnityEngine;
+
+public abstract class PlayerTask : MonoBehaviour
+{
+ public int Index { get; internal set; }
+
+ public uint Id { get; internal set; }
+
+ public PlayerControl Owner { get; internal set; }
+
+ public abstract int TaskStep { get; }
+
+ public abstract bool IsComplete { get; }
+
+ public Vector2 Location
+ {
+ get
+ {
+ this.LocationDirty = false;
+ return this.FindObjectPos().transform.position;
+ }
+ }
+
+ public SystemTypes StartAt;
+
+ public TaskTypes TaskType;
+
+ public Minigame MinigamePrefab;
+
+ public bool HasLocation;
+
+ public bool LocationDirty = true;
+
+ public abstract void Initialize();
+
+ public virtual void OnRemove()
+ {
+ }
+
+ public abstract bool ValidConsole(global::Console console);
+
+ public abstract void Complete();
+
+ public abstract void AppendTaskText(StringBuilder sb);
+
+ internal static bool TaskIsEmergency(PlayerTask arg)
+ {
+ return arg is NoOxyTask || arg is HudOverrideTask || arg is ReactorTask || arg is ElectricTask;
+ }
+
+ protected List<global::Console> FindConsoles()
+ {
+ List<global::Console> list = new List<global::Console>();
+ global::Console[] allConsoles = ShipStatus.Instance.AllConsoles;
+ for (int i = 0; i < allConsoles.Length; i++)
+ {
+ if (this.ValidConsole(allConsoles[i]))
+ {
+ list.Add(allConsoles[i]);
+ }
+ }
+ return list;
+ }
+
+ public static bool PlayerHasHudTask(PlayerControl localPlayer)
+ {
+ if (!localPlayer)
+ {
+ return true;
+ }
+ for (int i = 0; i < localPlayer.myTasks.Count; i++)
+ {
+ if (localPlayer.myTasks[i] is HudOverrideTask)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ protected List<Vector2> FindObjectsPos()
+ {
+ List<Vector2> list = new List<Vector2>();
+ global::Console[] allConsoles = ShipStatus.Instance.AllConsoles;
+ for (int i = 0; i < allConsoles.Length; i++)
+ {
+ if (this.ValidConsole(allConsoles[i]))
+ {
+ list.Add(allConsoles[i].transform.position);
+ }
+ }
+ return list;
+ }
+
+ protected global::Console FindSpecialConsole(Func<global::Console, bool> func)
+ {
+ global::Console[] allConsoles = ShipStatus.Instance.AllConsoles;
+ for (int i = 0; i < allConsoles.Length; i++)
+ {
+ if (func(allConsoles[i]))
+ {
+ return allConsoles[i];
+ }
+ }
+ return null;
+ }
+
+ protected global::Console FindObjectPos()
+ {
+ global::Console[] allConsoles = ShipStatus.Instance.AllConsoles;
+ for (int i = 0; i < allConsoles.Length; i++)
+ {
+ if (this.ValidConsole(allConsoles[i]))
+ {
+ return allConsoles[i];
+ }
+ }
+ Debug.LogError("Couldn't find location for task: " + base.name);
+ return null;
+ }
+
+ protected static bool AllTasksCompleted(PlayerControl player)
+ {
+ for (int i = 0; i < player.myTasks.Count; i++)
+ {
+ PlayerTask playerTask = player.myTasks[i];
+ if (playerTask is NormalPlayerTask && !playerTask.IsComplete)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/Client/Assembly-CSharp/PlayerVoteArea.cs b/Client/Assembly-CSharp/PlayerVoteArea.cs
new file mode 100644
index 0000000..d23a2a0
--- /dev/null
+++ b/Client/Assembly-CSharp/PlayerVoteArea.cs
@@ -0,0 +1,211 @@
+using System;
+using System.Collections;
+using Hazel;
+using UnityEngine;
+
+public class PlayerVoteArea : MonoBehaviour
+{
+ public MeetingHud Parent { get; set; }
+
+ public sbyte TargetPlayerId;
+
+ public const byte DeadBit = 128;
+
+ public const byte VotedBit = 64;
+
+ public const byte ReportedBit = 32;
+
+ public const byte VoteMask = 15;
+
+ public GameObject Buttons;
+
+ public SpriteRenderer PlayerIcon;
+
+ public SpriteRenderer Flag;
+
+ public SpriteRenderer Megaphone;
+
+ public SpriteRenderer Overlay;
+
+ public TextRenderer NameText;
+
+ public bool isDead;
+
+ public bool didVote;
+
+ public bool didReport;
+
+ public sbyte votedFor;
+
+ public bool voteComplete;
+
+ public bool resultsShowing;
+
+ public void SetDead(bool isMe, bool didReport, bool isDead)
+ {
+ this.isDead = isDead;
+ this.didReport = didReport;
+ this.Megaphone.enabled = didReport;
+ this.Overlay.gameObject.SetActive(false);
+ this.Overlay.transform.GetChild(0).gameObject.SetActive(isDead);
+ }
+
+ public void SetDisabled()
+ {
+ if (this.isDead)
+ {
+ return;
+ }
+ if (this.Overlay)
+ {
+ this.Overlay.gameObject.SetActive(true);
+ this.Overlay.transform.GetChild(0).gameObject.SetActive(false);
+ return;
+ }
+ base.GetComponent<SpriteRenderer>().enabled = false;
+ }
+
+ public void SetEnabled()
+ {
+ if (this.isDead)
+ {
+ return;
+ }
+ if (this.Overlay)
+ {
+ this.Overlay.gameObject.SetActive(false);
+ return;
+ }
+ base.GetComponent<SpriteRenderer>().enabled = true;
+ }
+
+ public IEnumerator CoAnimateOverlay()
+ {
+ this.Overlay.gameObject.SetActive(this.isDead);
+ if (this.isDead)
+ {
+ Transform xMark = this.Overlay.transform.GetChild(0);
+ this.Overlay.color = Palette.ClearWhite;
+ xMark.localScale = Vector3.zero;
+ float fadeDuration = 0.5f;
+ for (float t = 0f; t < fadeDuration; t += Time.deltaTime)
+ {
+ this.Overlay.color = Color.Lerp(Palette.ClearWhite, Color.white, t / fadeDuration);
+ yield return null;
+ }
+ this.Overlay.color = Color.white;
+ float scaleDuration = 0.15f;
+ for (float t = 0f; t < scaleDuration; t += Time.deltaTime)
+ {
+ float num = Mathf.Lerp(3f, 1f, t / scaleDuration);
+ xMark.transform.localScale = new Vector3(num, num, num);
+ yield return null;
+ }
+ xMark.transform.localScale = Vector3.one;
+ xMark = null;
+ }
+ else if (this.didReport)
+ {
+ float scaleDuration = 1f;
+ for (float fadeDuration = 0f; fadeDuration < scaleDuration; fadeDuration += Time.deltaTime)
+ {
+ float num2 = fadeDuration / scaleDuration;
+ float num3 = PlayerVoteArea.TriangleWave(num2 * 3f) * 2f - 1f;
+ this.Megaphone.transform.localEulerAngles = new Vector3(0f, 0f, num3 * 30f);
+ num3 = Mathf.Lerp(0.7f, 1.2f, PlayerVoteArea.TriangleWave(num2 * 2f));
+ this.Megaphone.transform.localScale = new Vector3(num3, num3, num3);
+ yield return null;
+ }
+ this.Megaphone.transform.localEulerAngles = Vector3.zero;
+ this.Megaphone.transform.localScale = Vector3.one;
+ }
+ yield break;
+ }
+
+ private static float TriangleWave(float t)
+ {
+ t -= (float)((int)t);
+ if (t < 0.5f)
+ {
+ return t * 2f;
+ }
+ return 1f - (t - 0.5f) * 2f;
+ }
+
+ internal void SetVote(sbyte suspectIdx)
+ {
+ this.didVote = true;
+ this.votedFor = suspectIdx;
+ this.Flag.enabled = true;
+ }
+
+ public void UnsetVote()
+ {
+ this.Flag.enabled = false;
+ this.votedFor = 0;
+ this.didVote = false;
+ }
+
+ public void ClearButtons()
+ {
+ this.Buttons.SetActive(false);
+ }
+
+ public void ClearForResults()
+ {
+ this.resultsShowing = true;
+ this.Flag.enabled = false;
+ }
+
+ public void VoteForMe()
+ {
+ if (!this.voteComplete)
+ {
+ this.Parent.Confirm(this.TargetPlayerId);
+ }
+ }
+
+ public void Select()
+ {
+ if (PlayerControl.LocalPlayer.Data.IsDead)
+ {
+ return;
+ }
+ if (this.isDead)
+ {
+ return;
+ }
+ if (!this.voteComplete && this.Parent.Select((int)this.TargetPlayerId))
+ {
+ this.Buttons.SetActive(true);
+ }
+ }
+
+ public void Cancel()
+ {
+ this.Buttons.SetActive(false);
+ }
+
+ public void Serialize(MessageWriter writer)
+ {
+ byte state = this.GetState();
+ writer.Write(state);
+ }
+
+ public void Deserialize(MessageReader reader)
+ {
+ byte b = reader.ReadByte();
+ this.votedFor = (sbyte)((b & 15) - 1);
+ this.isDead = ((b & 128) > 0);
+ this.didVote = ((b & 64) > 0);
+ this.didReport = ((b & 32) > 0);
+ this.Flag.enabled = (this.didVote && !this.resultsShowing);
+ this.Overlay.gameObject.SetActive(this.isDead);
+ this.Megaphone.enabled = this.didReport;
+ }
+
+ public byte GetState()
+ {
+ return (byte)((int)(this.votedFor + 1 & 15) | (this.isDead ? 128 : 0) | (this.didVote ? 64 : 0) | (this.didReport ? 32 : 0));
+ }
+}
diff --git a/Client/Assembly-CSharp/PoolableBehavior.cs b/Client/Assembly-CSharp/PoolableBehavior.cs
new file mode 100644
index 0000000..9f3cc11
--- /dev/null
+++ b/Client/Assembly-CSharp/PoolableBehavior.cs
@@ -0,0 +1,17 @@
+using System;
+using UnityEngine;
+
+public class PoolableBehavior : MonoBehaviour
+{
+ [HideInInspector]
+ public IObjectPool OwnerPool;
+
+ public virtual void Reset()
+ {
+ }
+
+ public void Awake()
+ {
+ this.OwnerPool = DefaultPool.Instance;
+ }
+}
diff --git a/Client/Assembly-CSharp/PoolablePlayer.cs b/Client/Assembly-CSharp/PoolablePlayer.cs
new file mode 100644
index 0000000..5b948fb
--- /dev/null
+++ b/Client/Assembly-CSharp/PoolablePlayer.cs
@@ -0,0 +1,45 @@
+using System;
+using UnityEngine;
+
+public class PoolablePlayer : MonoBehaviour
+{
+ public SpriteRenderer Body;
+
+ public SpriteRenderer[] Hands;
+
+ public SpriteRenderer HatSlot;
+
+ public SpriteRenderer SkinSlot;
+
+ public SpriteRenderer PetSlot;
+
+ public TextRenderer NameText;
+
+ public void SetFlipX(bool flipped)
+ {
+ this.Body.flipX = flipped;
+ this.SkinSlot.flipX = !flipped;
+ this.PetSlot.flipX = flipped;
+ this.HatSlot.flipX = !flipped;
+ if (flipped)
+ {
+ Vector3 localPosition = this.HatSlot.transform.localPosition;
+ localPosition.x = -localPosition.x;
+ this.HatSlot.transform.localPosition = localPosition;
+ }
+ }
+
+ public void SetDeadFlipX(bool flipped)
+ {
+ this.Body.flipX = flipped;
+ this.PetSlot.flipX = flipped;
+ this.HatSlot.flipX = flipped;
+ if (flipped)
+ {
+ Vector3 localPosition = this.HatSlot.transform.localPosition;
+ localPosition.x = -localPosition.x;
+ localPosition.y = 0.725f;
+ this.HatSlot.transform.localPosition = localPosition;
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/PooledMapIcon.cs b/Client/Assembly-CSharp/PooledMapIcon.cs
new file mode 100644
index 0000000..8e75ff3
--- /dev/null
+++ b/Client/Assembly-CSharp/PooledMapIcon.cs
@@ -0,0 +1,35 @@
+using System;
+using UnityEngine;
+
+public class PooledMapIcon : PoolableBehavior
+{
+ public float NormalSize = 0.3f;
+
+ public int lastMapTaskStep = -1;
+
+ public SpriteRenderer rend;
+
+ public AlphaPulse alphaPulse;
+
+ public void Update()
+ {
+ if (this.alphaPulse.enabled)
+ {
+ float num = Mathf.Abs(Mathf.Cos((this.alphaPulse.Offset + Time.time) * 3.1415927f / this.alphaPulse.Duration));
+ if ((double)num > 0.9)
+ {
+ num -= 0.9f;
+ num = this.NormalSize + num;
+ base.transform.localScale = new Vector3(num, num, num);
+ }
+ }
+ }
+
+ public override void Reset()
+ {
+ this.lastMapTaskStep = -1;
+ this.alphaPulse.enabled = false;
+ this.rend.material.SetFloat("_Outline", 0f);
+ base.Reset();
+ }
+}
diff --git a/Client/Assembly-CSharp/PowerTools/SpriteAnim.cs b/Client/Assembly-CSharp/PowerTools/SpriteAnim.cs
new file mode 100644
index 0000000..863854e
--- /dev/null
+++ b/Client/Assembly-CSharp/PowerTools/SpriteAnim.cs
@@ -0,0 +1,255 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+
+namespace PowerTools
+{
+ [RequireComponent(typeof(Animator))]
+ [DisallowMultipleComponent]
+ public class SpriteAnim : SpriteAnimEventHandler
+ {
+ public bool Playing
+ {
+ get
+ {
+ return this.IsPlaying(null);
+ }
+ }
+
+ public bool Paused
+ {
+ get
+ {
+ return this.IsPaused();
+ }
+ set
+ {
+ if (value)
+ {
+ this.Pause();
+ return;
+ }
+ this.Resume();
+ }
+ }
+
+ public float Speed
+ {
+ get
+ {
+ return this.m_speed;
+ }
+ set
+ {
+ this.SetSpeed(value);
+ }
+ }
+
+ public float Time
+ {
+ get
+ {
+ return this.GetTime();
+ }
+ set
+ {
+ this.SetTime(value);
+ }
+ }
+
+ public float NormalizedTime
+ {
+ get
+ {
+ return this.GetNormalisedTime();
+ }
+ set
+ {
+ this.SetNormalizedTime(value);
+ }
+ }
+
+ public AnimationClip Clip
+ {
+ get
+ {
+ return this.m_currAnim;
+ }
+ }
+
+ public string ClipName
+ {
+ get
+ {
+ if (!(this.m_currAnim != null))
+ {
+ return string.Empty;
+ }
+ return this.m_currAnim.name;
+ }
+ }
+
+ private static readonly string STATE_NAME = "a";
+
+ private static readonly string CONTROLLER_PATH = "SpriteAnimController";
+
+ [SerializeField]
+ private AnimationClip m_defaultAnim;
+
+ private static RuntimeAnimatorController m_sharedAnimatorController = null;
+
+ private Animator m_animator;
+
+ private AnimatorOverrideController m_controller;
+
+ private SpriteAnimNodes m_nodes;
+
+ private List<KeyValuePair<AnimationClip, AnimationClip>> m_clipPairList = new List<KeyValuePair<AnimationClip, AnimationClip>>(1);
+
+ private AnimationClip m_currAnim;
+
+ private float m_speed = 1f;
+
+ public void Play(AnimationClip anim = null, float speed = 1f)
+ {
+ if (anim == null)
+ {
+ anim = (this.m_currAnim ? this.m_currAnim : this.m_defaultAnim);
+ if (anim == null)
+ {
+ return;
+ }
+ }
+ if (!this.m_animator.enabled)
+ {
+ this.m_animator.enabled = true;
+ }
+ if (this.m_nodes != null)
+ {
+ this.m_nodes.Reset();
+ }
+ this.m_clipPairList[0] = new KeyValuePair<AnimationClip, AnimationClip>(this.m_clipPairList[0].Key, anim);
+ this.m_controller.ApplyOverrides(this.m_clipPairList);
+ this.m_animator.Update(0f);
+ this.m_animator.Play(SpriteAnim.STATE_NAME, 0, 0f);
+ this.m_speed = Mathf.Max(0f, speed);
+ this.m_animator.speed = this.m_speed;
+ this.m_currAnim = anim;
+ this.m_animator.Update(0f);
+ }
+
+ public void Stop()
+ {
+ this.m_animator.enabled = false;
+ }
+
+ public void Pause()
+ {
+ this.m_animator.speed = 0f;
+ }
+
+ public void Resume()
+ {
+ this.m_animator.speed = this.m_speed;
+ }
+
+ public AnimationClip GetCurrentAnimation()
+ {
+ return this.m_currAnim;
+ }
+
+ public bool IsPlaying(AnimationClip clip = null)
+ {
+ return (clip == null || this.m_currAnim == clip) && this.m_animator.GetCurrentAnimatorStateInfo(0).normalizedTime < 1f;
+ }
+
+ public bool IsPlaying(string animName)
+ {
+ return !(this.m_currAnim == null) && this.m_currAnim.name == animName && this.m_animator.GetCurrentAnimatorStateInfo(0).normalizedTime < 1f;
+ }
+
+ public bool IsPaused()
+ {
+ return !(this.m_currAnim == null) && this.m_animator.speed == 0f;
+ }
+
+ public void SetSpeed(float speed)
+ {
+ this.m_speed = Mathf.Max(0f, speed);
+ this.m_animator.speed = this.m_speed;
+ }
+
+ public float GetSpeed()
+ {
+ return this.m_speed;
+ }
+
+ public float GetTime()
+ {
+ if (this.m_currAnim != null)
+ {
+ return this.m_animator.GetCurrentAnimatorStateInfo(0).normalizedTime * this.m_currAnim.length;
+ }
+ return 0f;
+ }
+
+ public void SetTime(float time)
+ {
+ if (this.m_currAnim == null || this.m_currAnim.length <= 0f)
+ {
+ return;
+ }
+ this.SetNormalizedTime(time / this.m_currAnim.length);
+ }
+
+ public float GetNormalisedTime()
+ {
+ if (this.m_currAnim != null)
+ {
+ return this.m_animator.GetCurrentAnimatorStateInfo(0).normalizedTime;
+ }
+ return 0f;
+ }
+
+ public void SetNormalizedTime(float ratio)
+ {
+ if (this.m_currAnim == null)
+ {
+ return;
+ }
+ this.m_animator.Play(SpriteAnim.STATE_NAME, 0, this.m_currAnim.isLooping ? Mathf.Repeat(ratio, 1f) : Mathf.Clamp01(ratio));
+ }
+
+ private void Awake()
+ {
+ this.m_controller = new AnimatorOverrideController();
+ if (SpriteAnim.m_sharedAnimatorController == null)
+ {
+ SpriteAnim.m_sharedAnimatorController = Resources.Load<RuntimeAnimatorController>(SpriteAnim.CONTROLLER_PATH);
+ }
+ this.m_controller.runtimeAnimatorController = SpriteAnim.m_sharedAnimatorController;
+ this.m_animator = base.GetComponent<Animator>();
+ this.m_animator.runtimeAnimatorController = this.m_controller;
+ this.m_controller.GetOverrides(this.m_clipPairList);
+ this.Play(this.m_defaultAnim, 1f);
+ this.m_nodes = base.GetComponent<SpriteAnimNodes>();
+ }
+
+ private void Reset()
+ {
+ if (base.GetComponent<RectTransform>() == null)
+ {
+ if (base.GetComponent<Sprite>() == null)
+ {
+ base.gameObject.AddComponent<SpriteRenderer>();
+ return;
+ }
+ }
+ else if (base.GetComponent<Image>() == null)
+ {
+ base.gameObject.AddComponent<Image>();
+ }
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/PowerTools/SpriteAnimEventHandler.cs b/Client/Assembly-CSharp/PowerTools/SpriteAnimEventHandler.cs
new file mode 100644
index 0000000..b97b8c2
--- /dev/null
+++ b/Client/Assembly-CSharp/PowerTools/SpriteAnimEventHandler.cs
@@ -0,0 +1,111 @@
+using System;
+using UnityEngine;
+
+namespace PowerTools
+{
+ [DisallowMultipleComponent]
+ public class SpriteAnimEventHandler : MonoBehaviour
+ {
+ private string m_eventWithObjectMessage;
+
+ private object m_eventWithObjectData;
+
+ public static class EventParser
+ {
+ public static readonly char MESSAGE_DELIMITER = '\t';
+
+ public static readonly string MESSAGE_NOPARAM = "_Anim";
+
+ public static readonly string MESSAGE_INT = "_AnimInt";
+
+ public static readonly string MESSAGE_FLOAT = "_AnimFloat";
+
+ public static readonly string MESSAGE_STRING = "_AnimString";
+
+ public static readonly string MESSAGE_OBJECT_FUNCNAME = "_AnimObjectFunc";
+
+ public static readonly string MESSAGE_OBJECT_DATA = "_AnimObjectData";
+
+ public static int ParseInt(ref string messageString)
+ {
+ int num = messageString.IndexOf(SpriteAnimEventHandler.EventParser.MESSAGE_DELIMITER);
+ int result = 0;
+ int.TryParse(messageString.Substring(num + 1), out result);
+ messageString = messageString.Substring(0, num);
+ return result;
+ }
+
+ public static float ParseFloat(ref string messageString)
+ {
+ int num = messageString.IndexOf(SpriteAnimEventHandler.EventParser.MESSAGE_DELIMITER);
+ float result = 0f;
+ float.TryParse(messageString.Substring(num + 1), out result);
+ messageString = messageString.Substring(0, num);
+ return result;
+ }
+
+ public static string ParseString(ref string messageString)
+ {
+ int num = messageString.IndexOf(SpriteAnimEventHandler.EventParser.MESSAGE_DELIMITER);
+ string result = messageString.Substring(num + 1);
+ messageString = messageString.Substring(0, num);
+ return result;
+ }
+ }
+
+ private void _Anim(string function)
+ {
+ base.SendMessageUpwards(function, SendMessageOptions.DontRequireReceiver);
+ }
+
+ private void _AnimInt(string messageString)
+ {
+ int num = SpriteAnimEventHandler.EventParser.ParseInt(ref messageString);
+ base.SendMessageUpwards(messageString, num, SendMessageOptions.DontRequireReceiver);
+ }
+
+ private void _AnimFloat(string messageString)
+ {
+ float num = SpriteAnimEventHandler.EventParser.ParseFloat(ref messageString);
+ base.SendMessageUpwards(messageString, num, SendMessageOptions.DontRequireReceiver);
+ }
+
+ private void _AnimString(string messageString)
+ {
+ string value = SpriteAnimEventHandler.EventParser.ParseString(ref messageString);
+ base.SendMessageUpwards(messageString, value, SendMessageOptions.DontRequireReceiver);
+ }
+
+ private void _AnimObjectFunc(string funcName)
+ {
+ if (this.m_eventWithObjectData != null)
+ {
+ base.SendMessageUpwards(funcName, this.m_eventWithObjectData, SendMessageOptions.DontRequireReceiver);
+ this.m_eventWithObjectMessage = null;
+ this.m_eventWithObjectData = null;
+ return;
+ }
+ if (!string.IsNullOrEmpty(this.m_eventWithObjectMessage))
+ {
+ Debug.LogError("Animation event with object parameter had no object");
+ }
+ this.m_eventWithObjectMessage = funcName;
+ }
+
+ private void _AnimObjectData(UnityEngine.Object data)
+ {
+ if (!string.IsNullOrEmpty(this.m_eventWithObjectMessage))
+ {
+ base.SendMessageUpwards(this.m_eventWithObjectMessage, data, SendMessageOptions.DontRequireReceiver);
+ this.m_eventWithObjectMessage = null;
+ this.m_eventWithObjectData = null;
+ return;
+ }
+ if (this.m_eventWithObjectData != null)
+ {
+ Debug.LogError("Animation event with object parameter had no object");
+ }
+ this.m_eventWithObjectData = data;
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/PowerTools/SpriteAnimNodeSync.cs b/Client/Assembly-CSharp/PowerTools/SpriteAnimNodeSync.cs
new file mode 100644
index 0000000..e5fad22
--- /dev/null
+++ b/Client/Assembly-CSharp/PowerTools/SpriteAnimNodeSync.cs
@@ -0,0 +1,36 @@
+using System;
+using UnityEngine;
+
+namespace PowerTools
+{
+ public class SpriteAnimNodeSync : MonoBehaviour
+ {
+ public int NodeId;
+
+ public SpriteAnimNodes Parent;
+
+ public SpriteRenderer ParentRenderer;
+
+ public SpriteRenderer Renderer;
+
+ public void LateUpdate()
+ {
+ if (this.Renderer && this.ParentRenderer)
+ {
+ this.Renderer.flipX = this.ParentRenderer.flipX;
+ }
+ Vector3 localPosition = base.transform.localPosition;
+ Vector3 localPosition2 = this.Parent.GetLocalPosition(this.NodeId, false);
+ localPosition.x = localPosition2.x;
+ localPosition.y = localPosition2.y;
+ base.transform.localPosition = localPosition;
+ float angle = this.Parent.GetAngle(this.NodeId);
+ if (!this.Renderer || !this.Renderer.flipX)
+ {
+ base.transform.eulerAngles = new Vector3(0f, 0f, angle);
+ return;
+ }
+ base.transform.eulerAngles = new Vector3(0f, 0f, -angle);
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/PowerTools/SpriteAnimNodes.cs b/Client/Assembly-CSharp/PowerTools/SpriteAnimNodes.cs
new file mode 100644
index 0000000..2669ac1
--- /dev/null
+++ b/Client/Assembly-CSharp/PowerTools/SpriteAnimNodes.cs
@@ -0,0 +1,232 @@
+using System;
+using UnityEngine;
+
+namespace PowerTools
+{
+ public class SpriteAnimNodes : MonoBehaviour
+ {
+ public static readonly int NUM_NODES = 10;
+
+ [SerializeField]
+ [HideInInspector]
+ private Vector2 m_node0 = Vector2.zero;
+
+ [SerializeField]
+ [HideInInspector]
+ private Vector2 m_node1 = Vector2.zero;
+
+ [SerializeField]
+ [HideInInspector]
+ private Vector2 m_node2 = Vector2.zero;
+
+ [SerializeField]
+ [HideInInspector]
+ private Vector2 m_node3 = Vector2.zero;
+
+ [SerializeField]
+ [HideInInspector]
+ private Vector2 m_node4 = Vector2.zero;
+
+ [SerializeField]
+ [HideInInspector]
+ private Vector2 m_node5 = Vector2.zero;
+
+ [SerializeField]
+ [HideInInspector]
+ private Vector2 m_node6 = Vector2.zero;
+
+ [SerializeField]
+ [HideInInspector]
+ private Vector2 m_node7 = Vector2.zero;
+
+ [SerializeField]
+ [HideInInspector]
+ private Vector2 m_node8 = Vector2.zero;
+
+ [SerializeField]
+ [HideInInspector]
+ private Vector2 m_node9 = Vector2.zero;
+
+ [SerializeField]
+ [HideInInspector]
+ private float m_ang0;
+
+ [SerializeField]
+ [HideInInspector]
+ private float m_ang1;
+
+ [SerializeField]
+ [HideInInspector]
+ private float m_ang2;
+
+ [SerializeField]
+ [HideInInspector]
+ private float m_ang3;
+
+ [SerializeField]
+ [HideInInspector]
+ private float m_ang4;
+
+ [SerializeField]
+ [HideInInspector]
+ private float m_ang5;
+
+ [SerializeField]
+ [HideInInspector]
+ private float m_ang6;
+
+ [SerializeField]
+ [HideInInspector]
+ private float m_ang7;
+
+ [SerializeField]
+ [HideInInspector]
+ private float m_ang8;
+
+ [SerializeField]
+ [HideInInspector]
+ private float m_ang9;
+
+ private SpriteRenderer m_spriteRenderer;
+
+ public Vector3 GetPosition(int nodeId, bool ignoredPivot = false)
+ {
+ if (this.m_spriteRenderer == null)
+ {
+ this.m_spriteRenderer = base.GetComponent<SpriteRenderer>();
+ }
+ if (this.m_spriteRenderer == null || this.m_spriteRenderer.sprite == null)
+ {
+ return Vector2.zero;
+ }
+ Vector3 vector = this.GetLocalPosition(nodeId, ignoredPivot);
+ vector = base.transform.rotation * vector;
+ vector.Scale(base.transform.lossyScale);
+ return vector + base.transform.position;
+ }
+
+ public Vector3 GetLocalPosition(int nodeId, bool ignoredPivot = false)
+ {
+ if (this.m_spriteRenderer == null)
+ {
+ this.m_spriteRenderer = base.GetComponent<SpriteRenderer>();
+ }
+ if (this.m_spriteRenderer == null || this.m_spriteRenderer.sprite == null)
+ {
+ return Vector2.zero;
+ }
+ Vector3 vector = this.GetPositionRaw(nodeId);
+ vector.y = -vector.y;
+ if (ignoredPivot)
+ {
+ vector += this.m_spriteRenderer.sprite.rect.size * 0.5f - this.m_spriteRenderer.sprite.pivot;
+ }
+ vector *= 1f / this.m_spriteRenderer.sprite.pixelsPerUnit;
+ if (this.m_spriteRenderer.flipX)
+ {
+ vector.x = -vector.x;
+ }
+ if (this.m_spriteRenderer.flipY)
+ {
+ vector.y = -vector.y;
+ }
+ return vector;
+ }
+
+ public float GetAngle(int nodeId)
+ {
+ float angleRaw = this.GetAngleRaw(nodeId);
+ if (this.m_spriteRenderer == null)
+ {
+ this.m_spriteRenderer = base.GetComponent<SpriteRenderer>();
+ }
+ if (this.m_spriteRenderer == null || this.m_spriteRenderer.sprite == null)
+ {
+ return 0f;
+ }
+ return angleRaw + base.transform.eulerAngles.z;
+ }
+
+ public Vector2 GetPositionRaw(int nodeId)
+ {
+ switch (nodeId)
+ {
+ case 0:
+ return this.m_node0;
+ case 1:
+ return this.m_node1;
+ case 2:
+ return this.m_node2;
+ case 3:
+ return this.m_node3;
+ case 4:
+ return this.m_node4;
+ case 5:
+ return this.m_node5;
+ case 6:
+ return this.m_node6;
+ case 7:
+ return this.m_node7;
+ case 8:
+ return this.m_node8;
+ case 9:
+ return this.m_node9;
+ default:
+ return Vector2.zero;
+ }
+ }
+
+ public float GetAngleRaw(int nodeId)
+ {
+ switch (nodeId)
+ {
+ case 0:
+ return this.m_ang0;
+ case 1:
+ return this.m_ang1;
+ case 2:
+ return this.m_ang2;
+ case 3:
+ return this.m_ang3;
+ case 4:
+ return this.m_ang4;
+ case 5:
+ return this.m_ang5;
+ case 6:
+ return this.m_ang6;
+ case 7:
+ return this.m_ang7;
+ case 8:
+ return this.m_ang8;
+ case 9:
+ return this.m_ang9;
+ default:
+ return 0f;
+ }
+ }
+
+ public void Reset()
+ {
+ this.m_node0 = Vector2.zero;
+ this.m_node1 = Vector2.zero;
+ this.m_node2 = Vector2.zero;
+ this.m_node3 = Vector2.zero;
+ this.m_node4 = Vector2.zero;
+ this.m_node5 = Vector2.zero;
+ this.m_node6 = Vector2.zero;
+ this.m_node7 = Vector2.zero;
+ this.m_node8 = Vector2.zero;
+ this.m_node9 = Vector2.zero;
+ this.m_ang0 = 0f;
+ this.m_ang1 = 0f;
+ this.m_ang2 = 0f;
+ this.m_ang3 = 0f;
+ this.m_ang4 = 0f;
+ this.m_ang5 = 0f;
+ this.m_ang6 = 0f;
+ this.m_ang7 = 0f;
+ this.m_ang8 = 0f;
+ this.m_ang9 = 0f;
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/PowerTools/WaitForAnimationFinish.cs b/Client/Assembly-CSharp/PowerTools/WaitForAnimationFinish.cs
new file mode 100644
index 0000000..f4f083c
--- /dev/null
+++ b/Client/Assembly-CSharp/PowerTools/WaitForAnimationFinish.cs
@@ -0,0 +1,55 @@
+using System;
+using System.Collections;
+using UnityEngine;
+
+namespace PowerTools
+{
+ public class WaitForAnimationFinish : IEnumerator
+ {
+ public object Current
+ {
+ get
+ {
+ return null;
+ }
+ }
+
+ private SpriteAnim animator;
+
+ private AnimationClip clip;
+
+ private bool first = true;
+
+ public WaitForAnimationFinish(SpriteAnim animator, AnimationClip clip)
+ {
+ this.animator = animator;
+ this.clip = clip;
+ this.animator.Play(this.clip, 1f);
+ }
+
+ public bool MoveNext()
+ {
+ if (this.first)
+ {
+ this.first = false;
+ return true;
+ }
+ bool result;
+ try
+ {
+ result = this.animator.IsPlaying(this.clip);
+ }
+ catch
+ {
+ result = false;
+ }
+ return result;
+ }
+
+ public void Reset()
+ {
+ this.first = true;
+ this.animator.Play(this.clip, 1f);
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/ProgressTracker.cs b/Client/Assembly-CSharp/ProgressTracker.cs
new file mode 100644
index 0000000..60cae92
--- /dev/null
+++ b/Client/Assembly-CSharp/ProgressTracker.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Linq;
+using UnityEngine;
+
+public class ProgressTracker : MonoBehaviour
+{
+ public MeshRenderer TileParent;
+
+ private float curValue;
+
+ public void Start()
+ {
+ this.TileParent.material.SetFloat("_Buckets", 1f);
+ this.TileParent.material.SetFloat("_FullBuckets", 0f);
+ }
+
+ public void FixedUpdate()
+ {
+ if (PlayerTask.PlayerHasHudTask(PlayerControl.LocalPlayer))
+ {
+ this.TileParent.enabled = false;
+ return;
+ }
+ if (!this.TileParent.enabled)
+ {
+ this.TileParent.enabled = true;
+ }
+ GameData instance = GameData.Instance;
+ if (instance && instance.TotalTasks > 0)
+ {
+ int num = DestroyableSingleton<TutorialManager>.InstanceExists ? 1 : (instance.AllPlayers.Count - PlayerControl.GameOptions.NumImpostors);
+ num -= instance.AllPlayers.Count((GameData.PlayerInfo p) => p.Disconnected);
+ float b = (float)instance.CompletedTasks / (float)instance.TotalTasks * (float)num;
+ this.curValue = Mathf.Lerp(this.curValue, b, Time.fixedDeltaTime * 2f);
+ this.TileParent.material.SetFloat("_Buckets", (float)num);
+ this.TileParent.material.SetFloat("_FullBuckets", this.curValue);
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/Properties/AssemblyInfo.cs b/Client/Assembly-CSharp/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..4480267
--- /dev/null
+++ b/Client/Assembly-CSharp/Properties/AssemblyInfo.cs
@@ -0,0 +1,6 @@
+using System;
+using System.Diagnostics;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+[assembly: AssemblyVersion("0.0.0.0")]
diff --git a/Client/Assembly-CSharp/PurchaseButton.cs b/Client/Assembly-CSharp/PurchaseButton.cs
new file mode 100644
index 0000000..56c3171
--- /dev/null
+++ b/Client/Assembly-CSharp/PurchaseButton.cs
@@ -0,0 +1,90 @@
+using System;
+using UnityEngine;
+
+public class PurchaseButton : MonoBehaviour
+{
+ public StoreMenu Parent { get; set; }
+
+ public SpriteRenderer PurchasedIcon;
+
+ public TextRenderer NameText;
+
+ public SpriteRenderer HatImage;
+
+ public Sprite MannequinFrame;
+
+ public SpriteRenderer Background;
+
+ public IBuyable Product;
+
+ public bool Purchased;
+
+ public string Name;
+
+ public string Price;
+
+ public string ProductId;
+
+ public void SetItem(IBuyable product, string productId, string name, string price, bool purchased)
+ {
+ this.Product = product;
+ this.Purchased = purchased;
+ this.Name = name;
+ this.Price = price;
+ this.ProductId = productId;
+ this.PurchasedIcon.enabled = this.Purchased;
+ if (this.Product is HatBehaviour)
+ {
+ HatBehaviour hat = (HatBehaviour)this.Product;
+ this.NameText.gameObject.SetActive(false);
+ this.HatImage.transform.parent.gameObject.SetActive(true);
+ PlayerControl.SetHatImage(hat, this.HatImage);
+ this.SetSquare();
+ return;
+ }
+ if (this.Product is SkinData)
+ {
+ SkinData skin = (SkinData)this.Product;
+ this.NameText.gameObject.SetActive(false);
+ this.HatImage.transform.parent.gameObject.SetActive(true);
+ this.HatImage.transform.parent.GetComponent<SpriteRenderer>().sprite = this.MannequinFrame;
+ this.HatImage.transform.parent.localPosition = new Vector3(0f, 0f, -0.01f);
+ this.HatImage.transform.parent.localScale = Vector3.one * 0.3f;
+ this.HatImage.transform.localPosition = new Vector3(0f, 0f, -0.01f);
+ this.HatImage.transform.localScale = Vector3.one * 2f;
+ PlayerControl.SetSkinImage(skin, this.HatImage);
+ this.SetSquare();
+ return;
+ }
+ if (this.Product is PetBehaviour)
+ {
+ PetBehaviour petBehaviour = (PetBehaviour)this.Product;
+ this.NameText.gameObject.SetActive(false);
+ this.HatImage.transform.parent.gameObject.SetActive(true);
+ this.HatImage.transform.parent.GetComponent<SpriteRenderer>().enabled = false;
+ this.HatImage.material = new Material(petBehaviour.rend.sharedMaterial);
+ PlayerControl.SetPetImage(petBehaviour, (int)SaveManager.BodyColor, this.HatImage);
+ this.SetSquare();
+ return;
+ }
+ this.NameText.Text = this.Name;
+ }
+
+ private void SetSquare()
+ {
+ this.Background.size = new Vector2(0.7f, 0.7f);
+ this.Background.GetComponent<BoxCollider2D>().size = new Vector2(0.7f, 0.7f);
+ this.PurchasedIcon.transform.localPosition = new Vector3(0f, 0f, -1f);
+ }
+
+ internal void SetPurchased()
+ {
+ this.Purchased = true;
+ this.PurchasedIcon.enabled = true;
+ }
+
+ public void DoPurchase()
+ {
+ this.Parent.SetProduct(this);
+ }
+}
diff --git a/Client/Assembly-CSharp/PurchaseStates.cs b/Client/Assembly-CSharp/PurchaseStates.cs
new file mode 100644
index 0000000..e2ceb83
--- /dev/null
+++ b/Client/Assembly-CSharp/PurchaseStates.cs
@@ -0,0 +1,9 @@
+using System;
+
+public enum PurchaseStates
+{
+ NotStarted,
+ Started,
+ Success,
+ Fail
+}
diff --git a/Client/Assembly-CSharp/RadioWaveBehaviour.cs b/Client/Assembly-CSharp/RadioWaveBehaviour.cs
new file mode 100644
index 0000000..c46234f
--- /dev/null
+++ b/Client/Assembly-CSharp/RadioWaveBehaviour.cs
@@ -0,0 +1,81 @@
+using System;
+using UnityEngine;
+
+[RequireComponent(typeof(MeshFilter))]
+[RequireComponent(typeof(MeshRenderer))]
+public class RadioWaveBehaviour : MonoBehaviour
+{
+ public int NumPoints = 128;
+
+ public FloatRange Width;
+
+ public FloatRange Height;
+
+ private Mesh mesh;
+
+ private Vector3[] vecs;
+
+ public float TickRate = 0.1f;
+
+ private float timer;
+
+ public int Skip = 2;
+
+ public float Frequency = 5f;
+
+ private int Tick;
+
+ public bool Random;
+
+ [Range(0f, 1f)]
+ public float NoiseLevel;
+
+ public void Start()
+ {
+ this.mesh = new Mesh();
+ base.GetComponent<MeshFilter>().mesh = this.mesh;
+ this.mesh.MarkDynamic();
+ this.vecs = new Vector3[this.NumPoints];
+ int[] array = new int[this.NumPoints];
+ for (int i = 0; i < this.vecs.Length; i++)
+ {
+ Vector3 vector = this.vecs[i];
+ vector.x = this.Width.Lerp((float)i / (float)this.vecs.Length);
+ vector.y = this.Height.Next();
+ this.vecs[i] = vector;
+ array[i] = i;
+ }
+ this.mesh.vertices = this.vecs;
+ this.mesh.SetIndices(array, MeshTopology.LineStrip, 0);
+ }
+
+ public void Update()
+ {
+ this.timer += Time.deltaTime;
+ if (this.timer > this.TickRate)
+ {
+ this.timer = 0f;
+ this.Tick++;
+ for (int i = 0; i < this.vecs.Length - this.Skip; i++)
+ {
+ this.vecs[i].y = this.vecs[i + this.Skip].y;
+ }
+ if (this.Random)
+ {
+ for (int j = 1; j <= this.Skip; j++)
+ {
+ this.vecs[this.vecs.Length - j].y = this.Height.Next();
+ }
+ }
+ else
+ {
+ float num = 1f - this.NoiseLevel;
+ for (int k = 0; k < this.Skip; k++)
+ {
+ this.vecs[this.vecs.Length - 1 - this.Skip + k].y = Mathf.Sin(((float)this.Tick + (float)k / (float)this.Skip) * this.Frequency) * this.Height.max * num + this.Height.Next() * this.NoiseLevel;
+ }
+ }
+ this.mesh.vertices = this.vecs;
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/RandomFill.cs b/Client/Assembly-CSharp/RandomFill.cs
new file mode 100644
index 0000000..352eafd
--- /dev/null
+++ b/Client/Assembly-CSharp/RandomFill.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+public class RandomFill<T>
+{
+ private T[] values;
+
+ private int idx;
+
+ public void Set(IEnumerable<T> values)
+ {
+ if (this.values == null)
+ {
+ this.values = values.ToArray<T>();
+ this.values.Shuffle<T>();
+ this.idx = this.values.Length - 1;
+ }
+ }
+
+ public T Get()
+ {
+ if (this.idx < 0)
+ {
+ this.values.Shuffle<T>();
+ this.idx = this.values.Length - 1;
+ }
+ T[] array = this.values;
+ int num = this.idx;
+ this.idx = num - 1;
+ return array[num];
+ }
+}
diff --git a/Client/Assembly-CSharp/ReactorMinigame.cs b/Client/Assembly-CSharp/ReactorMinigame.cs
new file mode 100644
index 0000000..21e1551
--- /dev/null
+++ b/Client/Assembly-CSharp/ReactorMinigame.cs
@@ -0,0 +1,110 @@
+using System;
+using UnityEngine;
+
+public class ReactorMinigame : Minigame
+{
+ private Color bad = new Color(1f, 0.16078432f, 0f);
+
+ private Color good = new Color(0.3019608f, 0.8862745f, 0.8352941f);
+
+ private ReactorSystemType reactor;
+
+ public TextRenderer statusText;
+
+ public SpriteRenderer hand;
+
+ private FloatRange YSweep = new FloatRange(-2.15f, 1.56f);
+
+ public SpriteRenderer sweeper;
+
+ public AudioClip HandSound;
+
+ private bool isButtonDown;
+
+ public override void Begin(PlayerTask task)
+ {
+ ShipStatus instance = ShipStatus.Instance;
+ if (!instance)
+ {
+ this.reactor = new ReactorSystemType();
+ }
+ else
+ {
+ this.reactor = (instance.Systems[SystemTypes.Reactor] as ReactorSystemType);
+ }
+ this.hand.color = this.bad;
+ }
+
+ public void ButtonDown()
+ {
+ if (PlayerControl.LocalPlayer.Data.IsImpostor)
+ {
+ return;
+ }
+ if (!this.reactor.IsActive)
+ {
+ return;
+ }
+ this.isButtonDown = !this.isButtonDown;
+ if (this.isButtonDown)
+ {
+ if (Constants.ShouldPlaySfx())
+ {
+ SoundManager.Instance.PlaySound(this.HandSound, true, 1f);
+ }
+ ShipStatus.Instance.RpcRepairSystem(SystemTypes.Reactor, (int)((byte)(64 | base.ConsoleId)));
+ }
+ else
+ {
+ SoundManager.Instance.StopSound(this.HandSound);
+ ShipStatus.Instance.RpcRepairSystem(SystemTypes.Reactor, (int)((byte)(32 | base.ConsoleId)));
+ }
+ try
+ {
+ ((SabotageTask)this.MyTask).MarkContributed();
+ }
+ catch
+ {
+ }
+ }
+
+ public void FixedUpdate()
+ {
+ if (!this.reactor.IsActive)
+ {
+ if (this.amClosing == Minigame.CloseState.None)
+ {
+ this.hand.color = this.good;
+ this.statusText.Text = "Reactor Nominal";
+ this.sweeper.enabled = false;
+ SoundManager.Instance.StopSound(this.HandSound);
+ base.StartCoroutine(base.CoStartClose(0.75f));
+ return;
+ }
+ }
+ else
+ {
+ if (!this.isButtonDown)
+ {
+ this.statusText.Text = "Hold to stop meltdown";
+ this.sweeper.enabled = false;
+ return;
+ }
+ this.statusText.Text = "Waiting for second user";
+ Vector3 localPosition = this.sweeper.transform.localPosition;
+ localPosition.y = this.YSweep.Lerp(Mathf.Sin(Time.time) * 0.5f + 0.5f);
+ this.sweeper.transform.localPosition = localPosition;
+ this.sweeper.enabled = true;
+ }
+ }
+
+ public override void Close()
+ {
+ SoundManager.Instance.StopSound(this.HandSound);
+ if (ShipStatus.Instance)
+ {
+ ShipStatus.Instance.RpcRepairSystem(SystemTypes.Reactor, (int)((byte)(32 | base.ConsoleId)));
+ }
+ base.Close();
+ }
+}
diff --git a/Client/Assembly-CSharp/ReactorRoomWire.cs b/Client/Assembly-CSharp/ReactorRoomWire.cs
new file mode 100644
index 0000000..6f65fb9
--- /dev/null
+++ b/Client/Assembly-CSharp/ReactorRoomWire.cs
@@ -0,0 +1,51 @@
+using System;
+using PowerTools;
+using UnityEngine;
+
+public class ReactorRoomWire : MonoBehaviour
+{
+ public global::Console myConsole;
+
+ public SpriteAnim Image;
+
+ public AnimationClip Normal;
+
+ public AnimationClip MeltdownNeed;
+
+ public AnimationClip MeltdownReady;
+
+ private ReactorSystemType reactor;
+
+ public void Update()
+ {
+ if (this.reactor == null)
+ {
+ ISystemType systemType;
+ if (!ShipStatus.Instance || !ShipStatus.Instance.Systems.TryGetValue(SystemTypes.Reactor, out systemType))
+ {
+ return;
+ }
+ this.reactor = (ReactorSystemType)systemType;
+ }
+ if (this.reactor.IsActive)
+ {
+ if (this.reactor.GetConsoleComplete(this.myConsole.ConsoleId))
+ {
+ if (!this.Image.IsPlaying(this.MeltdownReady))
+ {
+ this.Image.Play(this.MeltdownReady, 1f);
+ return;
+ }
+ }
+ else if (!this.Image.IsPlaying(this.MeltdownNeed))
+ {
+ this.Image.Play(this.MeltdownNeed, 1f);
+ return;
+ }
+ }
+ else if (!this.Image.IsPlaying(this.Normal))
+ {
+ this.Image.Play(this.Normal, 1f);
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/ReactorShipRoom.cs b/Client/Assembly-CSharp/ReactorShipRoom.cs
new file mode 100644
index 0000000..c1975c7
--- /dev/null
+++ b/Client/Assembly-CSharp/ReactorShipRoom.cs
@@ -0,0 +1,74 @@
+using System;
+using PowerTools;
+using UnityEngine;
+
+public class ReactorShipRoom : ShipRoom
+{
+ public Sprite normalManifolds;
+
+ public Sprite meltdownManifolds;
+
+ public SpriteRenderer Manifolds;
+
+ public AnimationClip normalReactor;
+
+ public AnimationClip meltdownReactor;
+
+ public SpriteAnim Reactor;
+
+ public AnimationClip normalHighFloor;
+
+ public AnimationClip meltdownHighFloor;
+
+ public SpriteAnim HighFloor;
+
+ public AnimationClip normalMidFloor;
+
+ public AnimationClip meltdownMidFloor;
+
+ public SpriteAnim MidFloor1;
+
+ public SpriteAnim MidFloor2;
+
+ public AnimationClip normalLowFloor;
+
+ public AnimationClip meltdownLowFloor;
+
+ public SpriteAnim LowFloor;
+
+ public AnimationClip[] normalPipes;
+
+ public AnimationClip[] meltdownPipes;
+
+ public SpriteAnim[] Pipes;
+
+ public void StartMeltdown()
+ {
+ DestroyableSingleton<HudManager>.Instance.StartReactorFlash();
+ this.Manifolds.sprite = this.meltdownManifolds;
+ this.Reactor.Play(this.meltdownReactor, 1f);
+ this.HighFloor.Play(this.meltdownHighFloor, 1f);
+ this.MidFloor1.Play(this.meltdownMidFloor, 1f);
+ this.MidFloor2.Play(this.meltdownMidFloor, 1f);
+ this.LowFloor.Play(this.meltdownLowFloor, 1f);
+ for (int i = 0; i < this.Pipes.Length; i++)
+ {
+ this.Pipes[i].Play(this.meltdownPipes[i], 1f);
+ }
+ }
+
+ public void StopMeltdown()
+ {
+ DestroyableSingleton<HudManager>.Instance.StopReactorFlash();
+ this.Manifolds.sprite = this.normalManifolds;
+ this.Reactor.Play(this.normalReactor, 1f);
+ this.HighFloor.Play(this.normalHighFloor, 1f);
+ this.MidFloor1.Play(this.normalMidFloor, 1f);
+ this.MidFloor2.Play(this.normalMidFloor, 1f);
+ this.LowFloor.Play(this.normalLowFloor, 1f);
+ for (int i = 0; i < this.Pipes.Length; i++)
+ {
+ this.Pipes[i].Play(this.normalPipes[i], 1f);
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/ReactorSystemType.cs b/Client/Assembly-CSharp/ReactorSystemType.cs
new file mode 100644
index 0000000..a1e1fa0
--- /dev/null
+++ b/Client/Assembly-CSharp/ReactorSystemType.cs
@@ -0,0 +1,137 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Hazel;
+
+public class ReactorSystemType : ISystemType, IActivatable
+{
+ public int UserCount
+ {
+ get
+ {
+ int num = 0;
+ int num2 = 0;
+ foreach (Tuple<byte, byte> tuple in this.UserConsolePairs)
+ {
+ int num3 = 1 << (int)tuple.Item2;
+ if ((num3 & num2) == 0)
+ {
+ num++;
+ num2 |= num3;
+ }
+ }
+ return num;
+ }
+ }
+
+ public bool IsActive
+ {
+ get
+ {
+ return this.Countdown < 10000f;
+ }
+ }
+
+ private const float SyncRate = 2f;
+
+ private float timer;
+
+ public const byte StartCountdown = 128;
+
+ public const byte AddUserOp = 64;
+
+ public const byte RemoveUserOp = 32;
+
+ public const byte ClearCountdown = 16;
+
+ public const float CountdownStopped = 10000f;
+
+ public const float ReactorDuration = 30f;
+
+ public const byte ConsoleIdMask = 3;
+
+ public const byte RequiredUserCount = 2;
+
+ public float Countdown = 10000f;
+
+ private HashSet<Tuple<byte, byte>> UserConsolePairs = new HashSet<Tuple<byte, byte>>();
+
+ public bool GetConsoleComplete(int consoleId)
+ {
+ return this.UserConsolePairs.Any((Tuple<byte, byte> kvp) => (int)kvp.Item2 == consoleId);
+ }
+
+ public void RepairDamage(PlayerControl player, byte opCode)
+ {
+ int num = (int)(opCode & 3);
+ if (opCode == 128 && !this.IsActive)
+ {
+ this.Countdown = 30f;
+ this.UserConsolePairs.Clear();
+ return;
+ }
+ if (opCode == 16)
+ {
+ this.Countdown = 10000f;
+ return;
+ }
+ if (opCode.HasAnyBit(64))
+ {
+ this.UserConsolePairs.Add(new Tuple<byte, byte>(player.PlayerId, (byte)num));
+ if (this.UserCount >= 2)
+ {
+ this.Countdown = 10000f;
+ return;
+ }
+ }
+ else if (opCode.HasAnyBit(32))
+ {
+ this.UserConsolePairs.Remove(new Tuple<byte, byte>(player.PlayerId, (byte)num));
+ }
+ }
+
+ public bool Detoriorate(float deltaTime)
+ {
+ if (this.IsActive)
+ {
+ if (DestroyableSingleton<HudManager>.Instance.ReactorFlash == null)
+ {
+ PlayerControl.LocalPlayer.AddSystemTask(SystemTypes.Reactor);
+ }
+ this.Countdown -= deltaTime;
+ this.timer += deltaTime;
+ if (this.timer > 2f)
+ {
+ this.timer = 0f;
+ return true;
+ }
+ }
+ else if (DestroyableSingleton<HudManager>.Instance.ReactorFlash != null)
+ {
+ ((ReactorShipRoom)ShipStatus.Instance.AllRooms.First((ShipRoom r) => r.RoomId == SystemTypes.Reactor)).StopMeltdown();
+ }
+ return false;
+ }
+
+ public void Serialize(MessageWriter writer, bool initialState)
+ {
+ writer.Write(this.Countdown);
+ writer.WritePacked(this.UserConsolePairs.Count);
+ foreach (Tuple<byte, byte> tuple in this.UserConsolePairs)
+ {
+ writer.Write(tuple.Item1);
+ writer.Write(tuple.Item2);
+ }
+ }
+
+ public void Deserialize(MessageReader reader, bool initialState)
+ {
+ this.Countdown = reader.ReadSingle();
+ this.UserConsolePairs.Clear();
+ int num = reader.ReadPackedInt32();
+ for (int i = 0; i < num; i++)
+ {
+ this.UserConsolePairs.Add(new Tuple<byte, byte>(reader.ReadByte(), reader.ReadByte()));
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/ReactorTask.cs b/Client/Assembly-CSharp/ReactorTask.cs
new file mode 100644
index 0000000..43f44ba
--- /dev/null
+++ b/Client/Assembly-CSharp/ReactorTask.cs
@@ -0,0 +1,85 @@
+using System;
+using System.Linq;
+using System.Text;
+using UnityEngine;
+
+public class ReactorTask : SabotageTask
+{
+ public override int TaskStep
+ {
+ get
+ {
+ return this.reactor.UserCount;
+ }
+ }
+
+ public override bool IsComplete
+ {
+ get
+ {
+ return this.isComplete;
+ }
+ }
+
+ private bool isComplete;
+
+ private ReactorSystemType reactor;
+
+ private bool even;
+
+ public override void Initialize()
+ {
+ ShipStatus instance = ShipStatus.Instance;
+ this.reactor = (ReactorSystemType)instance.Systems[SystemTypes.Reactor];
+ ((ReactorShipRoom)instance.AllRooms.First((ShipRoom r) => r.RoomId == SystemTypes.Reactor)).StartMeltdown();
+ base.SetupArrows();
+ }
+
+ private void FixedUpdate()
+ {
+ if (this.isComplete)
+ {
+ return;
+ }
+ if (!this.reactor.IsActive)
+ {
+ this.Complete();
+ }
+ }
+
+ public override bool ValidConsole(global::Console console)
+ {
+ return console.TaskTypes.Contains(TaskTypes.ResetReactor);
+ }
+
+ public override void OnRemove()
+ {
+ }
+
+ public override void Complete()
+ {
+ this.isComplete = true;
+ PlayerControl.LocalPlayer.RemoveTask(this);
+ if (this.didContribute)
+ {
+ StatsManager instance = StatsManager.Instance;
+ uint sabsFixed = instance.SabsFixed;
+ instance.SabsFixed = sabsFixed + 1U;
+ }
+ }
+
+ public override void AppendTaskText(StringBuilder sb)
+ {
+ this.even = !this.even;
+ Color color = this.even ? Color.yellow : Color.red;
+ sb.Append(color.ToTextColor());
+ sb.Append(DestroyableSingleton<TranslationController>.Instance.GetString(TaskTypes.ResetReactor));
+ sb.Append(" ");
+ sb.Append((int)this.reactor.Countdown);
+ sb.AppendLine(string.Format(" ({0}/{1})[]", this.reactor.UserCount, 2));
+ for (int i = 0; i < this.Arrows.Length; i++)
+ {
+ this.Arrows[i].image.color = color;
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/RefuelMinigame.cs b/Client/Assembly-CSharp/RefuelMinigame.cs
new file mode 100644
index 0000000..c54401f
--- /dev/null
+++ b/Client/Assembly-CSharp/RefuelMinigame.cs
@@ -0,0 +1,23 @@
+using System;
+
+public class RefuelMinigame : Minigame
+{
+ public RefuelStage[] Stages;
+
+ private RefuelStage stage;
+
+ public override void Begin(PlayerTask task)
+ {
+ base.Begin(task);
+ this.stage = this.Stages[(int)this.MyNormTask.Data[1]];
+ this.stage.MyNormTask = this.MyNormTask;
+ this.stage.gameObject.SetActive(true);
+ this.stage.Begin();
+ }
+
+ public override void Close()
+ {
+ SoundManager.Instance.StopSound(this.stage.RefuelSound);
+ base.Close();
+ }
+}
diff --git a/Client/Assembly-CSharp/RefuelStage.cs b/Client/Assembly-CSharp/RefuelStage.cs
new file mode 100644
index 0000000..41b64dc
--- /dev/null
+++ b/Client/Assembly-CSharp/RefuelStage.cs
@@ -0,0 +1,98 @@
+using System;
+using UnityEngine;
+
+public class RefuelStage : MonoBehaviour
+{
+ public NormalPlayerTask MyNormTask { get; set; }
+
+ public float RefuelDuration = 5f;
+
+ private Color darkRed = new Color32(90, 0, 0, byte.MaxValue);
+
+ private Color red = new Color32(byte.MaxValue, 58, 0, byte.MaxValue);
+
+ private Color green = Color.green;
+
+ public SpriteRenderer redLight;
+
+ public SpriteRenderer greenLight;
+
+ public VerticalGauge srcGauge;
+
+ public VerticalGauge destGauge;
+
+ public AudioClip RefuelSound;
+
+ private float timer;
+
+ private bool isDown;
+
+ private bool complete;
+
+ public void Begin()
+ {
+ this.timer = (float)this.MyNormTask.Data[0] / 255f;
+ }
+
+ public void FixedUpdate()
+ {
+ if (this.complete)
+ {
+ return;
+ }
+ if (this.isDown && this.timer < 1f)
+ {
+ this.timer += Time.fixedDeltaTime / this.RefuelDuration;
+ this.MyNormTask.Data[0] = (byte)Mathf.Min(255f, this.timer * 255f);
+ if (this.timer >= 1f)
+ {
+ this.complete = true;
+ this.greenLight.color = this.green;
+ this.redLight.color = this.darkRed;
+ this.MyNormTask.Data[0] = 0;
+ byte[] data = this.MyNormTask.Data;
+ int num = 1;
+ data[num] += 1;
+ if (this.MyNormTask.Data[1] % 2 == 0)
+ {
+ this.MyNormTask.NextStep();
+ }
+ this.MyNormTask.UpdateArrow();
+ }
+ }
+ this.destGauge.value = this.timer;
+ if (this.srcGauge)
+ {
+ this.srcGauge.value = 1f - this.timer;
+ }
+ }
+
+ public void Refuel()
+ {
+ if (this.complete)
+ {
+ base.transform.parent.GetComponent<Minigame>().Close();
+ return;
+ }
+ this.isDown = !this.isDown;
+ this.redLight.color = (this.isDown ? this.red : this.darkRed);
+ if (this.isDown)
+ {
+ if (Constants.ShouldPlaySfx())
+ {
+ SoundManager.Instance.PlayDynamicSound("Refuel", this.RefuelSound, true, new DynamicSound.GetDynamicsFunction(this.GetRefuelDynamics), true);
+ return;
+ }
+ }
+ else
+ {
+ SoundManager.Instance.StopSound(this.RefuelSound);
+ }
+ }
+
+ private void GetRefuelDynamics(AudioSource player, float dt)
+ {
+ player.volume = 1f;
+ player.pitch = Mathf.Lerp(0.75f, 1.25f, this.timer);
+ }
+}
diff --git a/Client/Assembly-CSharp/ReportButtonManager.cs b/Client/Assembly-CSharp/ReportButtonManager.cs
new file mode 100644
index 0000000..151b75b
--- /dev/null
+++ b/Client/Assembly-CSharp/ReportButtonManager.cs
@@ -0,0 +1,28 @@
+using System;
+using UnityEngine;
+
+public class ReportButtonManager : MonoBehaviour
+{
+ public SpriteRenderer renderer;
+
+ public void SetActive(bool isActive)
+ {
+ if (isActive)
+ {
+ this.renderer.color = Palette.EnabledColor;
+ this.renderer.material.SetFloat("_Desat", 0f);
+ return;
+ }
+ this.renderer.color = Palette.DisabledColor;
+ this.renderer.material.SetFloat("_Desat", 1f);
+ }
+
+ public void DoClick()
+ {
+ if (!base.isActiveAndEnabled)
+ {
+ return;
+ }
+ PlayerControl.LocalPlayer.ReportClosest();
+ }
+}
diff --git a/Client/Assembly-CSharp/ResSetter.cs b/Client/Assembly-CSharp/ResSetter.cs
new file mode 100644
index 0000000..d1632cf
--- /dev/null
+++ b/Client/Assembly-CSharp/ResSetter.cs
@@ -0,0 +1,29 @@
+using System;
+using System.IO;
+using UnityEngine;
+
+public class ResSetter : MonoBehaviour
+{
+ public int Width = 1438;
+
+ public int Height = 810;
+
+ private int cnt;
+
+ public void Start()
+ {
+ Screen.SetResolution(this.Width, this.Height, false);
+ }
+
+ public void Update()
+ {
+ if (Input.GetKeyDown(KeyCode.S))
+ {
+ Directory.CreateDirectory("C:\\AmongUsSS");
+ string format = "C:\\AmongUsSS\\Screenshot-{0}.png";
+ int num = this.cnt;
+ this.cnt = num + 1;
+ ScreenCapture.CaptureScreenshot(string.Format(format, num));
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/ResolutionManager.cs b/Client/Assembly-CSharp/ResolutionManager.cs
new file mode 100644
index 0000000..15a8ce7
--- /dev/null
+++ b/Client/Assembly-CSharp/ResolutionManager.cs
@@ -0,0 +1,44 @@
+using System;
+using UnityEngine;
+
+public static class ResolutionManager
+{
+ public static event Action<float> ResolutionChanged;
+
+ public static void SetResolution(int width, int height, bool fullscreen)
+ {
+ Action<float> resolutionChanged = ResolutionManager.ResolutionChanged;
+ if (resolutionChanged != null)
+ {
+ resolutionChanged((float)width / (float)height);
+ }
+ Screen.SetResolution(width, height, fullscreen);
+ }
+
+ public static void ToggleFullscreen()
+ {
+ bool flag = !Screen.fullScreen;
+ int width;
+ int height;
+ if (flag)
+ {
+ Resolution[] resolutions = Screen.resolutions;
+ Resolution resolution = resolutions[0];
+ for (int i = 0; i < resolutions.Length; i++)
+ {
+ if (resolution.height < resolutions[i].height)
+ {
+ resolution = resolutions[i];
+ }
+ }
+ width = resolution.width;
+ height = resolution.height;
+ }
+ else
+ {
+ width = 711;
+ height = 400;
+ }
+ ResolutionManager.SetResolution(width, height, flag);
+ }
+}
diff --git a/Client/Assembly-CSharp/ResolutionSlider.cs b/Client/Assembly-CSharp/ResolutionSlider.cs
new file mode 100644
index 0000000..088854a
--- /dev/null
+++ b/Client/Assembly-CSharp/ResolutionSlider.cs
@@ -0,0 +1,73 @@
+using System;
+using System.Linq;
+using UnityEngine;
+
+public class ResolutionSlider : MonoBehaviour
+{
+ private int targetIdx;
+
+ private Resolution targetResolution;
+
+ private bool targetFullscreen;
+
+ private Resolution[] allResolutions;
+
+ public SlideBar slider;
+
+ public ToggleButtonBehaviour Fullscreen;
+
+ public ToggleButtonBehaviour VSync;
+
+ public TextRenderer Display;
+
+ public void OnEnable()
+ {
+ this.allResolutions = (from r in Screen.resolutions
+ where r.height > 480
+ select r).ToArray<Resolution>();
+ this.targetResolution = Screen.currentResolution;
+ this.targetFullscreen = Screen.fullScreen;
+ this.targetIdx = this.allResolutions.IndexOf((Resolution e) => e.width == this.targetResolution.width && e.height == this.targetResolution.height);
+ this.slider.Value = (float)this.targetIdx / ((float)this.allResolutions.Length - 1f);
+ this.Display.Text = string.Format("{0}x{1}", this.targetResolution.width, this.targetResolution.height);
+ this.Fullscreen.UpdateText(this.targetFullscreen);
+ this.VSync.UpdateText(QualitySettings.vSyncCount != 0);
+ }
+
+ public void ToggleVSync()
+ {
+ bool flag = QualitySettings.vSyncCount != 0;
+ if (flag)
+ {
+ QualitySettings.vSyncCount = 0;
+ }
+ else
+ {
+ QualitySettings.vSyncCount = 1;
+ }
+ this.VSync.UpdateText(!flag);
+ }
+
+ public void ToggleFullscreen()
+ {
+ this.targetFullscreen = !this.targetFullscreen;
+ this.Fullscreen.UpdateText(this.targetFullscreen);
+ }
+
+ public void OnResChange(SlideBar slider)
+ {
+ int num = Mathf.RoundToInt((float)(this.allResolutions.Length - 1) * slider.Value);
+ if (num != this.targetIdx)
+ {
+ this.targetIdx = num;
+ this.targetResolution = this.allResolutions[num];
+ this.Display.Text = string.Format("{0}x{1}", this.targetResolution.width, this.targetResolution.height);
+ }
+ slider.Value = (float)this.targetIdx / ((float)this.allResolutions.Length - 1f);
+ }
+
+ public void SaveChange()
+ {
+ ResolutionManager.SetResolution(this.targetResolution.width, this.targetResolution.height, this.targetFullscreen);
+ }
+}
diff --git a/Client/Assembly-CSharp/RingBuffer.cs b/Client/Assembly-CSharp/RingBuffer.cs
new file mode 100644
index 0000000..e12313e
--- /dev/null
+++ b/Client/Assembly-CSharp/RingBuffer.cs
@@ -0,0 +1,75 @@
+using System;
+
+public class RingBuffer<T>
+{
+ public int Count { get; private set; }
+
+ public int Capacity
+ {
+ get
+ {
+ return this.Data.Length;
+ }
+ }
+
+ public T this[int i]
+ {
+ get
+ {
+ int num = (this.startIdx + i) % this.Data.Length;
+ return this.Data[num];
+ }
+ }
+
+ private readonly T[] Data;
+
+ private int startIdx;
+
+ public RingBuffer(int size)
+ {
+ this.Data = new T[size];
+ }
+
+ public T First()
+ {
+ return this.Data[this.startIdx];
+ }
+
+ public T Last()
+ {
+ int num = (this.startIdx + this.Count - 1) % this.Data.Length;
+ return this.Data[num];
+ }
+
+ public void Add(T item)
+ {
+ int num = (this.startIdx + this.Count) % this.Data.Length;
+ this.Data[num] = item;
+ if (this.Count < this.Data.Length)
+ {
+ int count = this.Count;
+ this.Count = count + 1;
+ return;
+ }
+ this.startIdx = (this.startIdx + 1) % this.Data.Length;
+ }
+
+ public T RemoveFirst()
+ {
+ if (this.Count == 0)
+ {
+ throw new InvalidOperationException("Data is empty");
+ }
+ T result = this.Data[this.startIdx];
+ this.startIdx = (this.startIdx + 1) % this.Data.Length;
+ int count = this.Count;
+ this.Count = count - 1;
+ return result;
+ }
+
+ public void Clear()
+ {
+ this.startIdx = 0;
+ this.Count = 0;
+ }
+}
diff --git a/Client/Assembly-CSharp/RoomTracker.cs b/Client/Assembly-CSharp/RoomTracker.cs
new file mode 100644
index 0000000..3c24ed6
--- /dev/null
+++ b/Client/Assembly-CSharp/RoomTracker.cs
@@ -0,0 +1,159 @@
+using System;
+using System.Collections;
+using UnityEngine;
+
+public class RoomTracker : MonoBehaviour
+{
+ public TextRenderer text;
+
+ public float SourceY = -2.5f;
+
+ public float TargetY = -3.25f;
+
+ private Collider2D playerCollider;
+
+ private ContactFilter2D filter;
+
+ private Collider2D[] buffer = new Collider2D[10];
+
+ public ShipRoom LastRoom;
+
+ private Coroutine slideInRoutine;
+
+ public void Awake()
+ {
+ this.filter = default(ContactFilter2D);
+ this.filter.layerMask = Constants.PlayersOnlyMask;
+ this.filter.useLayerMask = true;
+ this.filter.useTriggers = false;
+ }
+
+ public void OnDisable()
+ {
+ this.LastRoom = null;
+ Vector3 localPosition = this.text.transform.localPosition;
+ localPosition.y = this.TargetY;
+ this.text.transform.localPosition = localPosition;
+ }
+
+ public void FixedUpdate()
+ {
+ ShipRoom[] array = null;
+ if (LobbyBehaviour.Instance)
+ {
+ array = LobbyBehaviour.Instance.AllRooms;
+ }
+ if (ShipStatus.Instance)
+ {
+ array = ShipStatus.Instance.AllRooms;
+ }
+ if (array == null)
+ {
+ return;
+ }
+ ShipRoom shipRoom = null;
+ if (this.LastRoom)
+ {
+ int hitCount = this.LastRoom.roomArea.OverlapCollider(this.filter, this.buffer);
+ if (RoomTracker.CheckHitsForPlayer(this.buffer, hitCount))
+ {
+ shipRoom = this.LastRoom;
+ }
+ }
+ if (!shipRoom)
+ {
+ foreach (ShipRoom shipRoom2 in array)
+ {
+ if (shipRoom2.roomArea)
+ {
+ int hitCount2 = shipRoom2.roomArea.OverlapCollider(this.filter, this.buffer);
+ if (RoomTracker.CheckHitsForPlayer(this.buffer, hitCount2))
+ {
+ shipRoom = shipRoom2;
+ }
+ }
+ }
+ }
+ if (shipRoom)
+ {
+ if (this.LastRoom != shipRoom)
+ {
+ this.LastRoom = shipRoom;
+ if (this.slideInRoutine != null)
+ {
+ base.StopCoroutine(this.slideInRoutine);
+ }
+ if (shipRoom.RoomId != SystemTypes.Hallway)
+ {
+ this.slideInRoutine = base.StartCoroutine(this.CoSlideIn(shipRoom.RoomId));
+ return;
+ }
+ this.slideInRoutine = base.StartCoroutine(this.SlideOut());
+ return;
+ }
+ }
+ else if (this.LastRoom)
+ {
+ this.LastRoom = null;
+ if (this.slideInRoutine != null)
+ {
+ base.StopCoroutine(this.slideInRoutine);
+ }
+ this.slideInRoutine = base.StartCoroutine(this.SlideOut());
+ }
+ }
+
+ private IEnumerator CoSlideIn(SystemTypes newRoom)
+ {
+ yield return this.SlideOut();
+ Vector3 tempPos = this.text.transform.localPosition;
+ Color tempColor = Color.white;
+ this.text.Text = DestroyableSingleton<TranslationController>.Instance.GetString(newRoom);
+ float timer = 0f;
+ while (timer < 0.25f)
+ {
+ timer = Mathf.Min(0.25f, timer + Time.deltaTime);
+ float t = timer / 0.25f;
+ tempPos.y = Mathf.SmoothStep(this.TargetY, this.SourceY, t);
+ tempColor.a = Mathf.Lerp(0f, 1f, t);
+ this.text.transform.localPosition = tempPos;
+ this.text.Color = tempColor;
+ yield return null;
+ }
+ yield break;
+ }
+
+ private IEnumerator SlideOut()
+ {
+ Vector3 tempPos = this.text.transform.localPosition;
+ Color tempColor = Color.white;
+ float timer = FloatRange.ReverseLerp(tempPos.y, this.SourceY, this.TargetY) * 0.1f;
+ while (timer < 0.1f)
+ {
+ timer = Mathf.Min(0.1f, timer + Time.deltaTime);
+ float t = timer / 0.1f;
+ tempPos.y = Mathf.SmoothStep(this.SourceY, this.TargetY, t);
+ tempColor.a = Mathf.Lerp(1f, 0f, t);
+ this.text.transform.localPosition = tempPos;
+ this.text.Color = tempColor;
+ yield return null;
+ }
+ yield break;
+ }
+
+ private static bool CheckHitsForPlayer(Collider2D[] buffer, int hitCount)
+ {
+ if (!PlayerControl.LocalPlayer)
+ {
+ return false;
+ }
+ for (int i = 0; i < hitCount; i++)
+ {
+ if (buffer[i].gameObject == PlayerControl.LocalPlayer.gameObject)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/Client/Assembly-CSharp/SabotageSystemType.cs b/Client/Assembly-CSharp/SabotageSystemType.cs
new file mode 100644
index 0000000..59dd234
--- /dev/null
+++ b/Client/Assembly-CSharp/SabotageSystemType.cs
@@ -0,0 +1,135 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Hazel;
+
+public class SabotageSystemType : ISystemType
+{
+ public float Timer { get; set; }
+
+ public float PercentCool
+ {
+ get
+ {
+ return this.Timer / 30f;
+ }
+ }
+
+ public bool AnyActive
+ {
+ get
+ {
+ return this.specials.Any((IActivatable s) => s.IsActive);
+ }
+ }
+
+ public const float SpecialSabDelay = 30f;
+
+ private List<IActivatable> specials;
+
+ private bool dirty;
+
+ private SabotageSystemType.DummySab dummy = new SabotageSystemType.DummySab();
+
+ public class DummySab : IActivatable
+ {
+ public bool IsActive
+ {
+ get
+ {
+ return this.timer > 0f;
+ }
+ }
+
+ public float timer;
+ }
+
+ public SabotageSystemType(IActivatable[] specials)
+ {
+ this.specials = new List<IActivatable>(specials);
+ this.specials.Add(this.dummy);
+ }
+
+ public bool Detoriorate(float deltaTime)
+ {
+ this.dummy.timer -= deltaTime;
+ if (this.Timer > 0f && !this.AnyActive)
+ {
+ this.Timer -= deltaTime;
+ if (this.Timer <= 0f)
+ {
+ return true;
+ }
+ }
+ return this.dirty;
+ }
+
+ public void ForceSabTime(float t)
+ {
+ this.dummy.timer = t;
+ }
+
+ public void RepairDamage(PlayerControl player, byte amount)
+ {
+ this.dirty = true;
+ if (this.Timer > 0f)
+ {
+ return;
+ }
+ if (MeetingHud.Instance)
+ {
+ return;
+ }
+ if (AmongUsClient.Instance.AmHost)
+ {
+ if (amount <= 7)
+ {
+ if (amount != 3)
+ {
+ if (amount == 7)
+ {
+ byte b = 4;
+ for (int i = 0; i < 5; i++)
+ {
+ if (BoolRange.Next(0.5f))
+ {
+ b |= (byte)(1 << i);
+ }
+ }
+ ShipStatus.Instance.RpcRepairSystem(SystemTypes.Electrical, (int)(b | 128));
+ }
+ }
+ else
+ {
+ ShipStatus.Instance.RepairSystem(SystemTypes.Reactor, player, 128);
+ }
+ }
+ else if (amount != 8)
+ {
+ if (amount == 14)
+ {
+ ShipStatus.Instance.RepairSystem(SystemTypes.Comms, player, 128);
+ }
+ }
+ else
+ {
+ ShipStatus.Instance.RepairSystem(SystemTypes.LifeSupp, player, 128);
+ }
+ }
+ this.Timer = 30f;
+ }
+
+ public void Serialize(MessageWriter writer, bool initialState)
+ {
+ writer.Write(this.Timer);
+ if (!initialState)
+ {
+ this.dirty = false;
+ }
+ }
+
+ public void Deserialize(MessageReader reader, bool initialState)
+ {
+ this.Timer = reader.ReadSingle();
+ }
+}
diff --git a/Client/Assembly-CSharp/SabotageTask.cs b/Client/Assembly-CSharp/SabotageTask.cs
new file mode 100644
index 0000000..2f3e21a
--- /dev/null
+++ b/Client/Assembly-CSharp/SabotageTask.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+
+public abstract class SabotageTask : PlayerTask
+{
+ protected bool didContribute;
+
+ public ArrowBehaviour[] Arrows;
+
+ public void MarkContributed()
+ {
+ this.didContribute = true;
+ }
+
+ protected void SetupArrows()
+ {
+ if (base.Owner.AmOwner)
+ {
+ List<global::Console> list = base.FindConsoles();
+ for (int i = 0; i < list.Count; i++)
+ {
+ int consoleId = list[i].ConsoleId;
+ this.Arrows[consoleId].target = list[i].transform.position;
+ this.Arrows[consoleId].gameObject.SetActive(true);
+ }
+ return;
+ }
+ for (int j = 0; j < this.Arrows.Length; j++)
+ {
+ this.Arrows[j].gameObject.SetActive(false);
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/SampleMinigame.cs b/Client/Assembly-CSharp/SampleMinigame.cs
new file mode 100644
index 0000000..fd60a67
--- /dev/null
+++ b/Client/Assembly-CSharp/SampleMinigame.cs
@@ -0,0 +1,382 @@
+using System;
+using System.Collections;
+using UnityEngine;
+
+public class SampleMinigame : Minigame
+{
+ private SampleMinigame.States State
+ {
+ get
+ {
+ return (SampleMinigame.States)this.MyNormTask.Data[0];
+ }
+ set
+ {
+ this.MyNormTask.Data[0] = (byte)value;
+ }
+ }
+
+ private int AnomalyId
+ {
+ get
+ {
+ return (int)this.MyNormTask.Data[1];
+ }
+ set
+ {
+ this.MyNormTask.Data[1] = (byte)value;
+ }
+ }
+
+ private static string[] ProcessingStrings = new string[]
+ {
+ "Take a break",
+ "Go grab a coffee",
+ "You dont need to wait",
+ "go do something else"
+ };
+
+ private const float PanelMoveDuration = 0.75f;
+
+ private const byte TubeMask = 15;
+
+ public TextRenderer UpperText;
+
+ public TextRenderer LowerText;
+
+ public float TimePerStep = 15f;
+
+ public FloatRange platformY = new FloatRange(-3.5f, -0.75f);
+
+ public FloatRange dropperX = new FloatRange(-1.25f, 1.25f);
+
+ public SpriteRenderer CenterPanel;
+
+ public SpriteRenderer Dropper;
+
+ public SpriteRenderer[] Tubes;
+
+ public SpriteRenderer[] Buttons;
+
+ public SpriteRenderer LowerButton;
+
+ public AudioClip ButtonSound;
+
+ public AudioClip PanelMoveSound;
+
+ public AudioClip FailSound;
+
+ public AudioClip[] DropSounds;
+
+ private RandomFill<AudioClip> dropSounds;
+
+ public enum States : byte
+ {
+ PrepareSample,
+ Complete = 16,
+ AwaitingStart = 32,
+ Selection = 64,
+ Processing = 128
+ }
+
+ public void Awake()
+ {
+ this.dropSounds = new RandomFill<AudioClip>();
+ this.dropSounds.Set(this.DropSounds);
+ }
+
+ public override void Begin(PlayerTask task)
+ {
+ base.Begin(task);
+ SampleMinigame.States state = this.State;
+ if (state <= SampleMinigame.States.AwaitingStart)
+ {
+ if (state != SampleMinigame.States.PrepareSample)
+ {
+ if (state != SampleMinigame.States.AwaitingStart)
+ {
+ return;
+ }
+ this.LowerText.Text = "Press To Begin -->";
+ this.SetPlatformTop();
+ return;
+ }
+ else
+ {
+ base.StartCoroutine(this.BringPanelUp(true));
+ }
+ }
+ else
+ {
+ if (state == SampleMinigame.States.Selection)
+ {
+ for (int i = 0; i < this.Tubes.Length; i++)
+ {
+ this.Tubes[i].color = Color.blue;
+ }
+ this.Tubes[this.AnomalyId].color = Color.red;
+ this.LowerText.Text = "Select Anomaly";
+ this.SetPlatformTop();
+ return;
+ }
+ if (state == SampleMinigame.States.Processing)
+ {
+ for (int j = 0; j < this.Tubes.Length; j++)
+ {
+ this.Tubes[j].color = Color.blue;
+ }
+ this.LowerText.Text = SampleMinigame.ProcessingStrings.Random<string>();
+ this.SetPlatformBottom();
+ return;
+ }
+ }
+ }
+
+ private void SetPlatformBottom()
+ {
+ Vector3 localPosition = this.CenterPanel.transform.localPosition;
+ localPosition.y = this.platformY.min;
+ this.CenterPanel.transform.localPosition = localPosition;
+ }
+
+ private void SetPlatformTop()
+ {
+ Vector3 localPosition = this.CenterPanel.transform.localPosition;
+ localPosition.y = this.platformY.max;
+ this.CenterPanel.transform.localPosition = localPosition;
+ }
+
+ public void FixedUpdate()
+ {
+ if (this.State == SampleMinigame.States.Processing)
+ {
+ if (this.MyNormTask.TaskTimer <= 0f)
+ {
+ this.State = SampleMinigame.States.Selection;
+ this.LowerText.Text = "Select Anomaly";
+ this.UpperText.Text = "";
+ this.AnomalyId = this.Tubes.RandomIdx<SpriteRenderer>();
+ this.Tubes[this.AnomalyId].color = Color.red;
+ this.LowerButton.color = Color.white;
+ base.StartCoroutine(this.BringPanelUp(false));
+ return;
+ }
+ this.UpperText.Text = "ETA: " + (int)this.MyNormTask.TaskTimer;
+ return;
+ }
+ else
+ {
+ if (this.State == SampleMinigame.States.Selection)
+ {
+ float num = Mathf.Cos(Time.time * 1.5f) - 0.2f;
+ Color color = new Color(num, 1f, num, 1f);
+ for (int i = 0; i < this.Buttons.Length; i++)
+ {
+ this.Buttons[i].color = color;
+ }
+ return;
+ }
+ if (this.State == SampleMinigame.States.AwaitingStart)
+ {
+ float num2 = Mathf.Cos(Time.time * 1.5f) - 0.2f;
+ Color color2 = new Color(num2, 1f, num2, 1f);
+ this.LowerButton.color = color2;
+ }
+ return;
+ }
+ }
+
+ public IEnumerator BringPanelUp(bool isBeginning)
+ {
+ if (Constants.ShouldPlaySfx())
+ {
+ SoundManager.Instance.PlaySound(this.PanelMoveSound, false, 1f);
+ }
+ WaitForFixedUpdate wait = new WaitForFixedUpdate();
+ Vector3 pos = this.CenterPanel.transform.localPosition;
+ for (float i = 0f; i < 0.75f; i += Time.deltaTime)
+ {
+ pos.y = this.platformY.Lerp(i / 0.75f);
+ this.CenterPanel.transform.localPosition = pos;
+ yield return wait;
+ }
+ if (isBeginning)
+ {
+ this.State = SampleMinigame.States.AwaitingStart;
+ this.LowerText.Text = "Press To Begin -->";
+ }
+ pos.y = this.platformY.max;
+ this.CenterPanel.transform.localPosition = pos;
+ yield break;
+ }
+
+ public IEnumerator BringPanelDown()
+ {
+ if (Constants.ShouldPlaySfx())
+ {
+ SoundManager.Instance.PlaySound(this.PanelMoveSound, false, 1f);
+ }
+ WaitForFixedUpdate wait = new WaitForFixedUpdate();
+ Vector3 pos = this.CenterPanel.transform.localPosition;
+ for (float i = 0f; i < 0.75f; i += Time.deltaTime)
+ {
+ pos.y = this.platformY.Lerp(1f - i / 0.75f);
+ this.CenterPanel.transform.localPosition = pos;
+ yield return wait;
+ }
+ pos.y = this.platformY.min;
+ this.CenterPanel.transform.localPosition = pos;
+ yield break;
+ }
+
+ private IEnumerator DropTube(int id)
+ {
+ if (Constants.ShouldPlaySfx())
+ {
+ SoundManager.Instance.PlaySound(this.dropSounds.Get(), false, 1f);
+ }
+ this.Tubes[id].color = Color.blue;
+ yield break;
+ }
+
+ public void SelectTube(int tubeId)
+ {
+ if (this.State != SampleMinigame.States.Selection)
+ {
+ return;
+ }
+ this.State = SampleMinigame.States.PrepareSample;
+ for (int i = 0; i < this.Buttons.Length; i++)
+ {
+ this.Buttons[i].color = Color.white;
+ }
+ base.StartCoroutine(this.CoSelectTube(this.AnomalyId, tubeId));
+ }
+
+ private IEnumerator CoSelectTube(int correctTube, int selectedTube)
+ {
+ if (selectedTube != correctTube)
+ {
+ if (Constants.ShouldPlaySfx())
+ {
+ SoundManager.Instance.PlaySound(this.FailSound, false, 1f);
+ }
+ this.UpperText.Text = "Bad Result";
+ this.LowerText.Text = "Bad Result";
+ for (int i = 0; i < this.Buttons.Length; i++)
+ {
+ this.Buttons[i].color = Color.red;
+ }
+ yield return new WaitForSeconds(0.25f);
+ for (int j = 0; j < this.Buttons.Length; j++)
+ {
+ this.Buttons[j].color = Color.white;
+ }
+ yield return new WaitForSeconds(0.25f);
+ for (int k = 0; k < this.Buttons.Length; k++)
+ {
+ this.Buttons[k].color = Color.red;
+ }
+ yield return new WaitForSeconds(0.25f);
+ for (int l = 0; l < this.Buttons.Length; l++)
+ {
+ this.Buttons[l].color = Color.white;
+ }
+ this.UpperText.Text = "";
+ }
+ else
+ {
+ if (Constants.ShouldPlaySfx())
+ {
+ SoundManager.Instance.PlaySound(this.ButtonSound, false, 0.6f);
+ }
+ this.UpperText.Text = "Thank you";
+ this.MyNormTask.NextStep();
+ if (this.MyNormTask.IsComplete)
+ {
+ this.State = SampleMinigame.States.Complete;
+ }
+ }
+ int num = this.MyNormTask.MaxStep - this.MyNormTask.taskStep;
+ if (num == 0)
+ {
+ this.LowerText.Text = "Tests Complete";
+ }
+ else
+ {
+ this.LowerText.Text = num + " more";
+ }
+ yield return this.BringPanelDown();
+ for (int m = 0; m < this.Tubes.Length; m++)
+ {
+ this.Tubes[m].color = Color.white;
+ }
+ if (!this.MyNormTask.IsComplete)
+ {
+ yield return this.BringPanelUp(true);
+ }
+ yield break;
+ }
+
+ public void NextStep()
+ {
+ if (this.State != SampleMinigame.States.AwaitingStart)
+ {
+ return;
+ }
+ this.State = SampleMinigame.States.Processing;
+ this.LowerButton.color = Color.white;
+ if (Constants.ShouldPlaySfx())
+ {
+ SoundManager.Instance.PlaySound(this.ButtonSound, false, 1f).volume = 0.6f;
+ }
+ base.StartCoroutine(this.CoStartProcessing());
+ }
+
+ private IEnumerator CoStartProcessing()
+ {
+ this.MyNormTask.TaskTimer = this.TimePerStep;
+ this.MyNormTask.TimerStarted = NormalPlayerTask.TimerState.Started;
+ yield return this.DropLiquid();
+ this.LowerText.Text = SampleMinigame.ProcessingStrings.Random<string>();
+ yield return this.BringPanelDown();
+ yield break;
+ }
+
+ private IEnumerator DropLiquid()
+ {
+ this.LowerText.Text = "Adding Reagent";
+ WaitForSeconds dropWait = new WaitForSeconds(0.25f);
+ WaitForFixedUpdate wait = new WaitForFixedUpdate();
+ Vector3 pos = this.Dropper.transform.localPosition;
+ yield return dropWait;
+ yield return this.DropTube(0);
+ int num;
+ for (int step = -2; step < 2; step = num)
+ {
+ float start = (float)step / 2f * 1.25f;
+ float xTarg = (float)(step + 1) / 2f * 1.25f;
+ for (float i = 0f; i < 0.15f; i += Time.deltaTime)
+ {
+ pos.x = Mathf.Lerp(start, xTarg, i / 0.15f);
+ this.Dropper.transform.localPosition = pos;
+ yield return wait;
+ }
+ pos.x = xTarg;
+ this.Dropper.transform.localPosition = pos;
+ yield return dropWait;
+ int id = step + 3;
+ yield return this.DropTube(id);
+ num = step + 1;
+ }
+ for (float xTarg = 0f; xTarg < 0.15f; xTarg += Time.deltaTime)
+ {
+ pos.x = this.dropperX.Lerp(1f - xTarg / 0.15f);
+ this.Dropper.transform.localPosition = pos;
+ yield return wait;
+ }
+ pos.x = this.dropperX.min;
+ this.Dropper.transform.localPosition = pos;
+ yield break;
+ }
+}
diff --git a/Client/Assembly-CSharp/SaveManager.cs b/Client/Assembly-CSharp/SaveManager.cs
new file mode 100644
index 0000000..8687d45
--- /dev/null
+++ b/Client/Assembly-CSharp/SaveManager.cs
@@ -0,0 +1,750 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using UnityEngine;
+
+public static class SaveManager
+{
+ public static Announcement LastAnnouncement
+ {
+ get
+ {
+ SaveManager.LoadAnnouncement();
+ return SaveManager.lastAnnounce;
+ }
+ set
+ {
+ SaveManager.lastAnnounce = value;
+ SaveManager.SaveAnnouncement();
+ }
+ }
+
+ public static DateTime LastStartDate
+ {
+ get
+ {
+ SaveManager.LoadSecureData2();
+ return SaveManager.lastStartDate;
+ }
+ set
+ {
+ SaveManager.LoadSecureData2();
+ if (SaveManager.lastStartDate < value)
+ {
+ SaveManager.lastStartDate = value;
+ SaveManager.SaveSecureData2();
+ }
+ }
+ }
+
+ public static int Month
+ {
+ get
+ {
+ return SaveManager.LastStartDate.Month;
+ }
+ }
+
+ public static bool BoughtNoAds
+ {
+ get
+ {
+ SaveManager.LoadSecureData();
+ return SaveManager.purchases.Contains("bought_ads");
+ }
+ }
+
+ public static bool CensorChat
+ {
+ get
+ {
+ SaveManager.LoadPlayerPrefs();
+ return SaveManager.censorChat;
+ }
+ set
+ {
+ SaveManager.LoadPlayerPrefs();
+ SaveManager.censorChat = value;
+ SaveManager.SavePlayerPrefs();
+ }
+ }
+
+ public static ShowAdsState ShowAdsScreen
+ {
+ get
+ {
+ SaveManager.LoadPlayerPrefs();
+ return (ShowAdsState)SaveManager.showAdsScreen;
+ }
+ set
+ {
+ SaveManager.LoadPlayerPrefs();
+ SaveManager.showAdsScreen = (byte)value;
+ SaveManager.SavePlayerPrefs();
+ }
+ }
+
+ public static bool SendDataScreen
+ {
+ get
+ {
+ SaveManager.LoadPlayerPrefs();
+ return SaveManager.sendDataScreen;
+ }
+ set
+ {
+ SaveManager.LoadPlayerPrefs();
+ SaveManager.sendDataScreen = value;
+ SaveManager.SavePlayerPrefs();
+ }
+ }
+
+ public static bool SendName
+ {
+ get
+ {
+ SaveManager.LoadPlayerPrefs();
+ return SaveManager.sendName && SaveManager.SendTelemetry;
+ }
+ set
+ {
+ SaveManager.LoadPlayerPrefs();
+ SaveManager.sendName = value;
+ SaveManager.SavePlayerPrefs();
+ }
+ }
+
+ public static bool SendTelemetry
+ {
+ get
+ {
+ SaveManager.LoadPlayerPrefs();
+ return SaveManager.sendTelemetry;
+ }
+ set
+ {
+ SaveManager.LoadPlayerPrefs();
+ SaveManager.sendTelemetry = value;
+ SaveManager.SavePlayerPrefs();
+ }
+ }
+
+ public static bool ShowMinPlayerWarning
+ {
+ get
+ {
+ SaveManager.LoadPlayerPrefs();
+ return SaveManager.showMinPlayerWarning;
+ }
+ set
+ {
+ SaveManager.LoadPlayerPrefs();
+ SaveManager.showMinPlayerWarning = value;
+ SaveManager.SavePlayerPrefs();
+ }
+ }
+
+ public static bool ShowOnlineHelp
+ {
+ get
+ {
+ SaveManager.LoadPlayerPrefs();
+ return SaveManager.showOnlineHelp;
+ }
+ set
+ {
+ SaveManager.LoadPlayerPrefs();
+ SaveManager.showOnlineHelp = value;
+ SaveManager.SavePlayerPrefs();
+ }
+ }
+
+ public static float SfxVolume
+ {
+ get
+ {
+ SaveManager.LoadPlayerPrefs();
+ return (float)SaveManager.sfxVolume / 255f;
+ }
+ set
+ {
+ SaveManager.LoadPlayerPrefs();
+ SaveManager.sfxVolume = (byte)(value * 255f);
+ SaveManager.SavePlayerPrefs();
+ }
+ }
+
+ public static float MusicVolume
+ {
+ get
+ {
+ SaveManager.LoadPlayerPrefs();
+ return (float)SaveManager.musicVolume / 255f;
+ }
+ set
+ {
+ SaveManager.LoadPlayerPrefs();
+ SaveManager.musicVolume = (byte)(value * 255f);
+ SaveManager.SavePlayerPrefs();
+ }
+ }
+
+ public static int TouchConfig
+ {
+ get
+ {
+ SaveManager.LoadPlayerPrefs();
+ return SaveManager.touchConfig;
+ }
+ set
+ {
+ SaveManager.LoadPlayerPrefs();
+ SaveManager.touchConfig = value;
+ SaveManager.SavePlayerPrefs();
+ }
+ }
+
+ public static float JoystickSize
+ {
+ get
+ {
+ SaveManager.LoadPlayerPrefs();
+ return SaveManager.joyStickSize;
+ }
+ set
+ {
+ SaveManager.LoadPlayerPrefs();
+ SaveManager.joyStickSize = value;
+ SaveManager.SavePlayerPrefs();
+ }
+ }
+
+ public static string PlayerName
+ {
+ get
+ {
+ SaveManager.LoadPlayerPrefs();
+ return SaveManager.lastPlayerName ?? "Enter Name";
+ }
+ set
+ {
+ SaveManager.LoadPlayerPrefs();
+ SaveManager.lastPlayerName = value;
+ SaveManager.SavePlayerPrefs();
+ }
+ }
+
+ public static uint LastPet
+ {
+ get
+ {
+ SaveManager.LoadPlayerPrefs();
+ return SaveManager.lastPet;
+ }
+ set
+ {
+ SaveManager.LoadPlayerPrefs();
+ SaveManager.lastPet = value;
+ SaveManager.SavePlayerPrefs();
+ }
+ }
+
+ public static uint LastHat
+ {
+ get
+ {
+ SaveManager.LoadPlayerPrefs();
+ return SaveManager.lastHat;
+ }
+ set
+ {
+ SaveManager.LoadPlayerPrefs();
+ SaveManager.lastHat = value;
+ SaveManager.SavePlayerPrefs();
+ }
+ }
+
+ public static uint LastSkin
+ {
+ get
+ {
+ SaveManager.LoadPlayerPrefs();
+ return SaveManager.lastSkin;
+ }
+ set
+ {
+ SaveManager.LoadPlayerPrefs();
+ SaveManager.lastSkin = value;
+ SaveManager.SavePlayerPrefs();
+ }
+ }
+
+ public static uint LastLanguage
+ {
+ get
+ {
+ SaveManager.LoadPlayerPrefs();
+ return SaveManager.lastLanguage;
+ }
+ set
+ {
+ SaveManager.LoadPlayerPrefs();
+ SaveManager.lastLanguage = value;
+ SaveManager.SavePlayerPrefs();
+ }
+ }
+
+ public static byte BodyColor
+ {
+ get
+ {
+ SaveManager.LoadPlayerPrefs();
+ return (byte)(SaveManager.colorConfig & 255U);
+ }
+ set
+ {
+ SaveManager.LoadPlayerPrefs();
+ SaveManager.colorConfig = ((SaveManager.colorConfig & 16776960U) | (uint)(value & byte.MaxValue));
+ SaveManager.SavePlayerPrefs();
+ }
+ }
+
+ public static GameOptionsData GameHostOptions
+ {
+ get
+ {
+ if (SaveManager.hostOptionsData == null)
+ {
+ SaveManager.hostOptionsData = SaveManager.LoadGameOptions("gameHostOptions");
+ }
+ SaveManager.hostOptionsData.NumImpostors = Mathf.Clamp(SaveManager.hostOptionsData.NumImpostors, 1, 3);
+ SaveManager.hostOptionsData.KillDistance = Mathf.Clamp(SaveManager.hostOptionsData.KillDistance, 0, 2);
+ return SaveManager.hostOptionsData;
+ }
+ set
+ {
+ SaveManager.hostOptionsData = value;
+ SaveManager.SaveGameOptions(SaveManager.hostOptionsData, "gameHostOptions");
+ }
+ }
+
+ public static GameOptionsData GameSearchOptions
+ {
+ get
+ {
+ GameOptionsData result;
+ if ((result = SaveManager.searchOptionsData) == null)
+ {
+ result = (SaveManager.searchOptionsData = SaveManager.LoadGameOptions("gameSearchOptions"));
+ }
+ return result;
+ }
+ set
+ {
+ SaveManager.searchOptionsData = value;
+ SaveManager.SaveGameOptions(SaveManager.searchOptionsData, "gameSearchOptions");
+ }
+ }
+
+ private static bool loaded;
+
+ private static bool loadedStats;
+
+ private static bool loadedAnnounce;
+
+ private static string lastPlayerName;
+
+ private static byte sfxVolume = byte.MaxValue;
+
+ private static byte musicVolume = byte.MaxValue;
+
+ private static bool showMinPlayerWarning = true;
+
+ private static bool showOnlineHelp = true;
+
+ private static bool sendDataScreen = false;
+
+ private static byte showAdsScreen = 0;
+
+ private static bool sendName = true;
+
+ private static bool sendTelemetry = true;
+
+ private static bool censorChat = true;
+
+ private static int touchConfig;
+
+ private static float joyStickSize = 1f;
+
+ private static uint colorConfig;
+
+ private static uint lastPet;
+
+ private static uint lastHat;
+
+ private static uint lastSkin;
+
+ private static uint lastLanguage;
+
+ private static GameOptionsData hostOptionsData;
+
+ private static GameOptionsData searchOptionsData;
+
+ private static Announcement lastAnnounce;
+
+ private static SaveManager.SecureDataFile secure2 = new SaveManager.SecureDataFile(Path.Combine(Application.persistentDataPath, "secure2"));
+
+ private static DateTime lastStartDate = DateTime.MinValue;
+
+ private static SaveManager.SecureDataFile purchaseFile = new SaveManager.SecureDataFile(Path.Combine(Application.persistentDataPath, "secureNew"));
+
+ private static HashSet<string> purchases = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
+
+ private class SecureDataFile
+ {
+ public bool Loaded { get; private set; }
+
+ private string filePath;
+
+ public SecureDataFile(string filePath)
+ {
+ this.filePath = filePath;
+ }
+
+ public BinaryReader LoadData()
+ {
+ this.Loaded = true;
+ Debug.Log("Loading secure: " + this.filePath);
+ if (File.Exists(this.filePath))
+ {
+ byte[] array = File.ReadAllBytes(this.filePath);
+ for (int i = 0; i < array.Length; i++)
+ {
+ byte[] array2 = array;
+ int num = i;
+ array2[num] ^= (byte)(i % 212);
+ }
+ try
+ {
+ BinaryReader binaryReader = new BinaryReader(new MemoryStream(array));
+ binaryReader.ReadString();
+ return binaryReader;
+ }
+ catch
+ {
+ Debug.Log("Deleted corrupt secure file inner");
+ this.Delete();
+ }
+ }
+ return null;
+ }
+
+ public void SaveData(params object[] items)
+ {
+ byte[] array;
+ using (MemoryStream memoryStream = new MemoryStream())
+ {
+ using (BinaryWriter binaryWriter = new BinaryWriter(memoryStream))
+ {
+ binaryWriter.Write(SystemInfo.deviceUniqueIdentifier);
+ foreach (object obj in items)
+ {
+ if (obj is long)
+ {
+ binaryWriter.Write((long)obj);
+ }
+ else if (obj is HashSet<string>)
+ {
+ foreach (string value in ((HashSet<string>)obj))
+ {
+ binaryWriter.Write(value);
+ }
+ }
+ }
+ binaryWriter.Flush();
+ memoryStream.Position = 0L;
+ array = memoryStream.ToArray();
+ }
+ }
+ for (int j = 0; j < array.Length; j++)
+ {
+ byte[] array2 = array;
+ int num = j;
+ array2[num] ^= (byte)(j % 212);
+ }
+ File.WriteAllBytes(this.filePath, array);
+ }
+
+ public void Delete()
+ {
+ try
+ {
+ File.Delete(this.filePath);
+ }
+ catch
+ {
+ }
+ }
+ }
+
+ private static void SaveSecureData2()
+ {
+ SaveManager.secure2.SaveData(new object[]
+ {
+ SaveManager.lastStartDate.Ticks
+ });
+ }
+
+ private static void LoadSecureData2()
+ {
+ if (SaveManager.secure2.Loaded)
+ {
+ return;
+ }
+ try
+ {
+ using (BinaryReader binaryReader = SaveManager.secure2.LoadData())
+ {
+ SaveManager.lastStartDate = new DateTime(binaryReader.ReadInt64());
+ }
+ }
+ catch
+ {
+ }
+ }
+
+ public static bool GetPurchase(string key)
+ {
+ SaveManager.LoadSecureData();
+ return SaveManager.purchases.Contains(key);
+ }
+
+ public static void SetPurchased(string key)
+ {
+ SaveManager.LoadSecureData();
+ SaveManager.purchases.Add(key ?? "null");
+ if (key == "bought_ads")
+ {
+ SaveManager.ShowAdsScreen = ShowAdsState.Purchased;
+ }
+ SaveManager.SaveSecureData();
+ }
+
+ private static void LoadSecureData()
+ {
+ if (SaveManager.purchaseFile.Loaded)
+ {
+ return;
+ }
+ try
+ {
+ using (BinaryReader binaryReader = SaveManager.purchaseFile.LoadData())
+ {
+ while (binaryReader.BaseStream.Position < binaryReader.BaseStream.Length)
+ {
+ SaveManager.purchases.Add(binaryReader.ReadString());
+ }
+ }
+ }
+ catch (NullReferenceException)
+ {
+ }
+ catch (Exception arg)
+ {
+ Debug.Log("Deleted corrupt secure file outer: " + arg);
+ SaveManager.purchaseFile.Delete();
+ }
+ }
+
+ private static void SaveSecureData()
+ {
+ SaveManager.purchaseFile.SaveData(new object[]
+ {
+ SaveManager.purchases
+ });
+ }
+
+ private static GameOptionsData LoadGameOptions(string filename)
+ {
+ string path = Path.Combine(Application.persistentDataPath, filename);
+ if (File.Exists(path))
+ {
+ using (FileStream fileStream = File.OpenRead(path))
+ {
+ using (BinaryReader binaryReader = new BinaryReader(fileStream))
+ {
+ return GameOptionsData.Deserialize(binaryReader) ?? new GameOptionsData();
+ }
+ }
+ }
+ return new GameOptionsData();
+ }
+
+ private static void SaveGameOptions(GameOptionsData data, string filename)
+ {
+ using (FileStream fileStream = new FileStream(Path.Combine(Application.persistentDataPath, filename), FileMode.Create, FileAccess.Write))
+ {
+ using (BinaryWriter binaryWriter = new BinaryWriter(fileStream))
+ {
+ data.Serialize(binaryWriter);
+ }
+ }
+ }
+
+ private static void LoadAnnouncement()
+ {
+ if (SaveManager.loadedAnnounce)
+ {
+ return;
+ }
+ SaveManager.loadedAnnounce = true;
+ string path = Path.Combine(Application.persistentDataPath, "announcement");
+ if (File.Exists(path))
+ {
+ string[] array = File.ReadAllText(path).Split(new char[1]);
+ if (array.Length == 3)
+ {
+ Announcement announcement = default(Announcement);
+ SaveManager.TryGetUint(array, 0, out announcement.Id);
+ announcement.AnnounceText = array[1];
+ SaveManager.TryGetInt(array, 2, out announcement.DateFetched);
+ SaveManager.lastAnnounce = announcement;
+ return;
+ }
+ SaveManager.lastAnnounce = default(Announcement);
+ }
+ }
+
+ public static void SaveAnnouncement()
+ {
+ File.WriteAllText(Path.Combine(Application.persistentDataPath, "announcement"), string.Join("\0", new object[]
+ {
+ SaveManager.lastAnnounce.Id,
+ SaveManager.lastAnnounce.AnnounceText,
+ SaveManager.lastAnnounce.DateFetched
+ }));
+ }
+
+ private static void LoadPlayerPrefs()
+ {
+ if (SaveManager.loaded)
+ {
+ return;
+ }
+ SaveManager.loaded = true;
+ string path = Path.Combine(Application.persistentDataPath, "playerPrefs");
+ if (File.Exists(path))
+ {
+ string[] array = File.ReadAllText(path).Split(new char[]
+ {
+ ','
+ });
+ SaveManager.lastPlayerName = array[0];
+ if (array.Length > 1)
+ {
+ int.TryParse(array[1], out SaveManager.touchConfig);
+ }
+ if (array.Length <= 2 || !uint.TryParse(array[2], out SaveManager.colorConfig))
+ {
+ SaveManager.colorConfig = (uint)((byte)(Palette.PlayerColors.RandomIdx<Color32>() << 16) | (byte)(Palette.PlayerColors.RandomIdx<Color32>() << 8) | (byte)Palette.PlayerColors.RandomIdx<Color32>());
+ }
+ SaveManager.TryGetBool(array, 4, out SaveManager.sendName, false);
+ SaveManager.TryGetBool(array, 5, out SaveManager.sendTelemetry, false);
+ SaveManager.TryGetBool(array, 6, out SaveManager.sendDataScreen, false);
+ SaveManager.TryGetByte(array, 7, out SaveManager.showAdsScreen);
+ SaveManager.TryGetBool(array, 8, out SaveManager.showMinPlayerWarning, false);
+ SaveManager.TryGetBool(array, 9, out SaveManager.showOnlineHelp, false);
+ SaveManager.TryGetUint(array, 10, out SaveManager.lastHat);
+ SaveManager.TryGetByte(array, 11, out SaveManager.sfxVolume);
+ SaveManager.TryGetByte(array, 12, out SaveManager.musicVolume);
+ SaveManager.TryGetFloat(array, 13, out SaveManager.joyStickSize, 1f);
+ SaveManager.TryGetUint(array, 15, out SaveManager.lastSkin);
+ SaveManager.TryGetUint(array, 16, out SaveManager.lastPet);
+ SaveManager.TryGetBool(array, 17, out SaveManager.censorChat, true);
+ SaveManager.TryGetUint(array, 18, out SaveManager.lastLanguage);
+ }
+ }
+
+ private static void SavePlayerPrefs()
+ {
+ SaveManager.LoadPlayerPrefs();
+ File.WriteAllText(Path.Combine(Application.persistentDataPath, "playerPrefs"), string.Join(",", new object[]
+ {
+ SaveManager.lastPlayerName,
+ SaveManager.touchConfig,
+ SaveManager.colorConfig,
+ 1,
+ SaveManager.sendName,
+ SaveManager.sendTelemetry,
+ SaveManager.sendDataScreen,
+ SaveManager.showAdsScreen,
+ SaveManager.showMinPlayerWarning,
+ SaveManager.showOnlineHelp,
+ SaveManager.lastHat,
+ SaveManager.sfxVolume,
+ SaveManager.musicVolume,
+ SaveManager.joyStickSize.ToString(CultureInfo.InvariantCulture),
+ 0L,
+ SaveManager.lastSkin,
+ SaveManager.lastPet,
+ SaveManager.censorChat,
+ SaveManager.lastLanguage
+ }));
+ }
+
+ private static void TryGetBool(string[] parts, int index, out bool value, bool @default = false)
+ {
+ value = @default;
+ if (parts.Length > index)
+ {
+ bool.TryParse(parts[index], out value);
+ }
+ }
+
+ private static void TryGetByte(string[] parts, int index, out byte value)
+ {
+ value = 0;
+ if (parts.Length > index)
+ {
+ byte.TryParse(parts[index], out value);
+ }
+ }
+
+ private static void TryGetFloat(string[] parts, int index, out float value, float @default = 0f)
+ {
+ value = @default;
+ if (parts.Length > index)
+ {
+ float.TryParse(parts[index], NumberStyles.Number, CultureInfo.InvariantCulture, out value);
+ }
+ }
+
+ private static void TryGetInt(string[] parts, int index, out int value)
+ {
+ value = 0;
+ if (parts.Length > index)
+ {
+ int.TryParse(parts[index], out value);
+ }
+ }
+
+ private static void TryGetUint(string[] parts, int index, out uint value)
+ {
+ value = 0U;
+ if (parts.Length > index)
+ {
+ uint.TryParse(parts[index], out value);
+ }
+ }
+
+ private static void TryGetDateTicks(string[] parts, int index, out DateTime value)
+ {
+ value = DateTime.MinValue;
+ long ticks;
+ if (parts.Length > index && long.TryParse(parts[index], out ticks))
+ {
+ value = new DateTime(ticks, DateTimeKind.Utc);
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/Scene0Controller.cs b/Client/Assembly-CSharp/Scene0Controller.cs
new file mode 100644
index 0000000..abada07
--- /dev/null
+++ b/Client/Assembly-CSharp/Scene0Controller.cs
@@ -0,0 +1,79 @@
+using System;
+using System.Collections;
+using UnityEngine;
+
+public class Scene0Controller : SceneController
+{
+ public float Duration = 3f;
+
+ public SpriteRenderer[] ExtraBoys;
+
+ public AnimationCurve PopInCurve;
+
+ public AnimationCurve PopOutCurve;
+
+ public float OutDuration = 0.2f;
+
+ public void OnEnable()
+ {
+ base.StartCoroutine(this.Run());
+ }
+
+ public void OnDisable()
+ {
+ for (int i = 0; i < this.ExtraBoys.Length; i++)
+ {
+ this.ExtraBoys[i].enabled = false;
+ }
+ }
+
+ private IEnumerator Run()
+ {
+ int lastBoy = 0;
+ float start = Time.time;
+ for (;;)
+ {
+ float num = (Time.time - start) / this.Duration;
+ int num2 = Mathf.RoundToInt((Mathf.Cos(3.1415927f * num + 3.1415927f) + 1f) / 2f * (float)this.ExtraBoys.Length);
+ if (lastBoy < num2)
+ {
+ base.StartCoroutine(this.PopIn(this.ExtraBoys[lastBoy]));
+ lastBoy = num2;
+ }
+ else if (lastBoy > num2)
+ {
+ lastBoy = num2;
+ base.StartCoroutine(this.PopOut(this.ExtraBoys[lastBoy]));
+ }
+ yield return null;
+ }
+ yield break;
+ }
+
+ private IEnumerator PopIn(SpriteRenderer boy)
+ {
+ boy.enabled = true;
+ for (float timer = 0f; timer < 0.2f; timer += Time.deltaTime)
+ {
+ float num = this.PopInCurve.Evaluate(timer / 0.2f);
+ boy.transform.localScale = new Vector3(num, num, num);
+ yield return null;
+ }
+ boy.transform.localScale = Vector3.one;
+ yield break;
+ }
+
+ private IEnumerator PopOut(SpriteRenderer boy)
+ {
+ boy.enabled = true;
+ for (float timer = 0f; timer < this.OutDuration; timer += Time.deltaTime)
+ {
+ float num = this.PopOutCurve.Evaluate(timer / this.OutDuration);
+ boy.transform.localScale = new Vector3(num, num, num);
+ yield return null;
+ }
+ boy.transform.localScale = Vector3.one;
+ boy.enabled = false;
+ yield break;
+ }
+}
diff --git a/Client/Assembly-CSharp/Scene1Controller.cs b/Client/Assembly-CSharp/Scene1Controller.cs
new file mode 100644
index 0000000..d1896ee
--- /dev/null
+++ b/Client/Assembly-CSharp/Scene1Controller.cs
@@ -0,0 +1,94 @@
+using System;
+using System.Collections;
+using UnityEngine;
+
+public class Scene1Controller : SceneController
+{
+ public PlayerAnimator[] players;
+
+ public DummyConsole[] Consoles;
+
+ public Vector2[] WayPoints;
+
+ public Camera backupCam;
+
+ public void OnDrawGizmos()
+ {
+ for (int i = 0; i < this.WayPoints.Length; i++)
+ {
+ Vector2 v = this.WayPoints[i];
+ Vector2 v2 = this.WayPoints[(i + 1) % this.WayPoints.Length];
+ Gizmos.DrawLine(v, v2);
+ }
+ }
+
+ public void OnEnable()
+ {
+ this.backupCam.cullingMask = 0;
+ base.StartCoroutine(this.RunPlayer(0));
+ base.StartCoroutine(this.RunPlayer(1));
+ }
+
+ public void OnDisable()
+ {
+ this.backupCam.cullingMask = (int.MaxValue ^ LayerMask.GetMask(new string[]
+ {
+ "UI"
+ }));
+ }
+
+ private IEnumerator RunPlayer(int idx)
+ {
+ PlayerAnimator myPlayer = this.players[idx];
+ for (;;)
+ {
+ int num;
+ for (int i = 0; i < this.WayPoints.Length; i = num)
+ {
+ bool willInterrupt = i == 2 || i == 5;
+ yield return myPlayer.WalkPlayerTo(this.WayPoints[i], willInterrupt, 0.1f);
+ if (willInterrupt)
+ {
+ yield return this.DoUse(idx, (i == 2) ? 0 : 1);
+ }
+ num = i + 1;
+ }
+ }
+ yield break;
+ }
+
+ private IEnumerator DoUse(int idx, int consoleid)
+ {
+ PlayerAnimator myPlayer = this.players[idx];
+ yield return Scene1Controller.WaitForSeconds(0.2f);
+ if (idx == 0)
+ {
+ yield return myPlayer.finger.MoveTo(myPlayer.UseButton.transform.position, 0.75f);
+ }
+ else
+ {
+ yield return myPlayer.finger.MoveTo(this.Consoles[consoleid].transform.position, 0.75f);
+ }
+ yield return Scene1Controller.WaitForSeconds(0.2f);
+ yield return myPlayer.finger.DoClick(0.4f);
+ yield return Scene1Controller.WaitForSeconds(0.2f);
+ if (!(myPlayer.joystick is DemoKeyboardStick))
+ {
+ yield return myPlayer.finger.MoveTo(myPlayer.joystick.transform.position, 0.75f);
+ }
+ else
+ {
+ yield return Scene1Controller.WaitForSeconds(0.75f);
+ }
+ yield break;
+ }
+
+ public static IEnumerator WaitForSeconds(float duration)
+ {
+ for (float time = 0f; time < duration; time += Time.deltaTime)
+ {
+ yield return null;
+ }
+ yield break;
+ }
+}
diff --git a/Client/Assembly-CSharp/SceneChanger.cs b/Client/Assembly-CSharp/SceneChanger.cs
new file mode 100644
index 0000000..0a58fa1
--- /dev/null
+++ b/Client/Assembly-CSharp/SceneChanger.cs
@@ -0,0 +1,27 @@
+using System;
+using UnityEngine;
+using UnityEngine.SceneManagement;
+using UnityEngine.UI;
+
+public class SceneChanger : MonoBehaviour
+{
+ public string TargetScene;
+
+ public Button.ButtonClickedEvent BeforeSceneChange;
+
+ public void Click()
+ {
+ this.BeforeSceneChange.Invoke();
+ SceneChanger.ChangeScene(this.TargetScene);
+ }
+
+ public static void ChangeScene(string target)
+ {
+ SceneManager.LoadScene(target);
+ }
+
+ public void ExitGame()
+ {
+ Application.Quit();
+ }
+}
diff --git a/Client/Assembly-CSharp/SceneController.cs b/Client/Assembly-CSharp/SceneController.cs
new file mode 100644
index 0000000..6129737
--- /dev/null
+++ b/Client/Assembly-CSharp/SceneController.cs
@@ -0,0 +1,6 @@
+using System;
+using UnityEngine;
+
+public class SceneController : MonoBehaviour
+{
+}
diff --git a/Client/Assembly-CSharp/ScreenJoystick.cs b/Client/Assembly-CSharp/ScreenJoystick.cs
new file mode 100644
index 0000000..f787ea3
--- /dev/null
+++ b/Client/Assembly-CSharp/ScreenJoystick.cs
@@ -0,0 +1,54 @@
+using System;
+using UnityEngine;
+
+public class ScreenJoystick : MonoBehaviour, IVirtualJoystick
+{
+ public Vector2 Delta { get; private set; }
+
+ private Collider2D[] hitBuffer = new Collider2D[20];
+
+ private Controller myController = new Controller();
+
+ private int touchId = -1;
+
+ private void FixedUpdate()
+ {
+ this.myController.Update();
+ if (this.touchId <= -1)
+ {
+ for (int i = 0; i < this.myController.Touches.Length; i++)
+ {
+ Controller.TouchState touchState = this.myController.Touches[i];
+ if (touchState.TouchStart)
+ {
+ bool flag = false;
+ int num = Physics2D.OverlapPointNonAlloc(touchState.Position, this.hitBuffer, Constants.NotShipMask);
+ for (int j = 0; j < num; j++)
+ {
+ Collider2D collider2D = this.hitBuffer[j];
+ if (collider2D.GetComponent<ButtonBehavior>() || collider2D.GetComponent<PassiveButton>())
+ {
+ flag = true;
+ break;
+ }
+ }
+ if (!flag)
+ {
+ this.touchId = i;
+ return;
+ }
+ }
+ }
+ return;
+ }
+ Controller.TouchState touchState2 = this.myController.Touches[this.touchId];
+ if (touchState2.IsDown)
+ {
+ Vector2 b = Camera.main.ViewportToWorldPoint(new Vector2(0.5f, 0.5f));
+ this.Delta = (touchState2.Position - b).normalized;
+ return;
+ }
+ this.touchId = -1;
+ this.Delta = Vector2.zero;
+ }
+}
diff --git a/Client/Assembly-CSharp/Scroller.cs b/Client/Assembly-CSharp/Scroller.cs
new file mode 100644
index 0000000..e38a9cb
--- /dev/null
+++ b/Client/Assembly-CSharp/Scroller.cs
@@ -0,0 +1,85 @@
+using System;
+using UnityEngine;
+
+public class Scroller : MonoBehaviour
+{
+ public bool AtTop
+ {
+ get
+ {
+ return this.Inner.localPosition.y <= this.YBounds.min + 0.25f;
+ }
+ }
+
+ public bool AtBottom
+ {
+ get
+ {
+ return this.Inner.localPosition.y >= this.YBounds.max - 0.25f;
+ }
+ }
+
+ public Transform Inner;
+
+ public Collider2D HitBox;
+
+ private Controller myController = new Controller();
+
+ private Vector3 origin;
+
+ public bool allowX;
+
+ public FloatRange XBounds = new FloatRange(-10f, 10f);
+
+ public bool allowY;
+
+ public FloatRange YBounds = new FloatRange(-10f, 10f);
+
+ public float YBoundPerItem;
+
+ public void FixedUpdate()
+ {
+ if (!this.Inner)
+ {
+ return;
+ }
+ Vector2 mouseScrollDelta = Input.mouseScrollDelta;
+ mouseScrollDelta.y = -mouseScrollDelta.y;
+ this.DoScroll(this.Inner.transform.localPosition, mouseScrollDelta);
+ this.myController.Update();
+ DragState dragState = this.myController.CheckDrag(this.HitBox, false);
+ if (dragState == DragState.TouchStart)
+ {
+ this.origin = this.Inner.transform.localPosition;
+ return;
+ }
+ if (dragState != DragState.Dragging)
+ {
+ return;
+ }
+ Vector2 del = this.myController.DragPosition - this.myController.DragStartPosition;
+ this.DoScroll(this.origin, del);
+ }
+
+ private void DoScroll(Vector3 origin, Vector2 del)
+ {
+ if (del.magnitude < 0.05f)
+ {
+ return;
+ }
+ if (!this.allowX)
+ {
+ del.x = 0f;
+ }
+ if (!this.allowY)
+ {
+ del.y = 0f;
+ }
+ Vector3 vector = origin + del;
+ vector.x = this.XBounds.Clamp(vector.x);
+ int childCount = this.Inner.transform.childCount;
+ float max = Mathf.Max(this.YBounds.min, this.YBounds.max + this.YBoundPerItem * (float)childCount);
+ vector.y = Mathf.Clamp(vector.y, this.YBounds.min, max);
+ this.Inner.transform.localPosition = vector;
+ }
+}
diff --git a/Client/Assembly-CSharp/SecurityCameraSystemType.cs b/Client/Assembly-CSharp/SecurityCameraSystemType.cs
new file mode 100644
index 0000000..f7a90ce
--- /dev/null
+++ b/Client/Assembly-CSharp/SecurityCameraSystemType.cs
@@ -0,0 +1,78 @@
+using System;
+using System.Collections.Generic;
+using Hazel;
+
+//监控器
+public class SecurityCameraSystemType : ISystemType
+{
+ public bool InUse
+ {
+ get
+ {
+ return this.PlayersUsing.Count > 0;
+ }
+ }
+
+ public const byte IncrementOp = 1;
+
+ public const byte DecrementOp = 2;
+
+ private HashSet<byte> PlayersUsing = new HashSet<byte>();
+
+ public bool Detoriorate(float deltaTime)
+ {
+ return false;
+ }
+
+ public void RepairDamage(PlayerControl player, byte amount)
+ {
+ if (amount == 1)
+ {
+ this.PlayersUsing.Add(player.PlayerId);
+ }
+ else
+ {
+ this.PlayersUsing.Remove(player.PlayerId);
+ }
+ this.UpdateCameras();
+ }
+
+ private void UpdateCameras()
+ {
+ for (int i = 0; i < ShipStatus.Instance.AllRooms.Length; i++)
+ {
+ ShipRoom shipRoom = ShipStatus.Instance.AllRooms[i];
+ if (shipRoom.survCamera)
+ {
+ if (this.InUse)
+ {
+ shipRoom.survCamera.Image.Play(shipRoom.survCamera.OnAnim, 1f);
+ }
+ else
+ {
+ shipRoom.survCamera.Image.Play(shipRoom.survCamera.OffAnim, 1f);
+ }
+ }
+ }
+ }
+
+ public void Serialize(MessageWriter writer, bool initialState)
+ {
+ writer.WritePacked(this.PlayersUsing.Count);
+ foreach (byte value in this.PlayersUsing)
+ {
+ writer.Write(value);
+ }
+ }
+
+ public void Deserialize(MessageReader reader, bool initialState)
+ {
+ this.PlayersUsing.Clear();
+ int num = reader.ReadPackedInt32();
+ for (int i = 0; i < num; i++)
+ {
+ this.PlayersUsing.Add(reader.ReadByte());
+ }
+ this.UpdateCameras();
+ }
+}
diff --git a/Client/Assembly-CSharp/ServerInfo.cs b/Client/Assembly-CSharp/ServerInfo.cs
new file mode 100644
index 0000000..f952619
--- /dev/null
+++ b/Client/Assembly-CSharp/ServerInfo.cs
@@ -0,0 +1,43 @@
+using System;
+using System.IO;
+using System.Net;
+
+public class ServerInfo
+{
+ public string Name = "Custom";
+
+ public string Ip = "0.0.0.0";
+
+ public bool Default;
+
+ public void Serialize(BinaryWriter writer)
+ {
+ writer.Write(this.Name);
+ writer.Write(this.Ip);
+ writer.Write(this.Default);
+ }
+
+ public static ServerInfo Deserialize(BinaryReader reader)
+ {
+ ServerInfo serverInfo = new ServerInfo();
+ serverInfo.Name = reader.ReadString();
+ serverInfo.Ip = reader.ReadString();
+ IPAddress ipaddress;
+ if (!IPAddress.TryParse(serverInfo.Ip, out ipaddress))
+ {
+ return null;
+ }
+ serverInfo.Default = reader.ReadBoolean();
+ return serverInfo;
+ }
+
+ internal static ServerInfo Deserialize(string[] parts)
+ {
+ return new ServerInfo
+ {
+ Name = parts[0],
+ Ip = parts[1],
+ Default = bool.Parse(parts[2])
+ };
+ }
+}
diff --git a/Client/Assembly-CSharp/ServerManager.cs b/Client/Assembly-CSharp/ServerManager.cs
new file mode 100644
index 0000000..0b28183
--- /dev/null
+++ b/Client/Assembly-CSharp/ServerManager.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Collections;
+using System.IO;
+using UnityEngine;
+
+public class ServerManager : DestroyableSingleton<ServerManager>
+{
+ public string OnlineNetAddress
+ {
+ get
+ {
+ return this.LastServer.Ip;
+ }
+ }
+
+ public const string DefaultOnlineServer = "50.116.1.42";
+
+ public static readonly ServerInfo DefaultServer = new ServerInfo
+ {
+ Name = "Primary",
+ Ip = "50.116.1.42",
+ Default = true
+ };
+
+ public ServerInfo[] availableServers;
+
+ public ServerInfo LastServer = ServerManager.DefaultServer;
+
+ private string serverInfoFile;
+
+ private ServerManager.UpdateState state;
+
+ private enum UpdateState
+ {
+ Connecting,
+ Failed,
+ Success
+ }
+
+ public void Start()
+ {
+ this.serverInfoFile = Path.Combine(Application.persistentDataPath, "serverInfo.dat");
+ this.LastServer = ServerManager.DefaultServer;
+ this.availableServers = new ServerInfo[]
+ {
+ this.LastServer
+ };
+ this.state = ServerManager.UpdateState.Success;
+ }
+
+ public IEnumerator WaitForServers()
+ {
+ while (this.state == ServerManager.UpdateState.Connecting)
+ {
+ yield return null;
+ }
+ yield break;
+ }
+}
diff --git a/Client/Assembly-CSharp/ServerSelectUi.cs b/Client/Assembly-CSharp/ServerSelectUi.cs
new file mode 100644
index 0000000..671ff7c
--- /dev/null
+++ b/Client/Assembly-CSharp/ServerSelectUi.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class ServerSelectUi : MonoBehaviour
+{
+ public ServerSelector ServerButtonPrefab;
+
+ public Vector3 ScrollStartArea;
+
+ public Scroller Slider;
+
+ public ServerSelector CustomServer;
+
+ private List<ServerSelector> myButtons = new List<ServerSelector>();
+
+ public void Start()
+ {
+ ServerInfo[] availableServers = DestroyableSingleton<ServerManager>.Instance.availableServers;
+ Vector3 scrollStartArea = this.ScrollStartArea;
+ for (int i = 0; i < availableServers.Length; i++)
+ {
+ if (!(availableServers[i].Name == "Custom"))
+ {
+ ServerSelector serverSelector = UnityEngine.Object.Instantiate<ServerSelector>(this.ServerButtonPrefab, this.Slider.Inner);
+ serverSelector.name = availableServers[i].Name;
+ this.myButtons.Add(serverSelector);
+ serverSelector.transform.localPosition = scrollStartArea;
+ serverSelector.Parent = this;
+ serverSelector.MyServer = availableServers[i];
+ if (availableServers[i].Default)
+ {
+ serverSelector.Select();
+ }
+ scrollStartArea.y -= 0.7f;
+ }
+ }
+ this.CustomServer.Parent = this;
+ this.myButtons.Add(this.CustomServer);
+ if (DestroyableSingleton<ServerManager>.Instance.LastServer.Name == "Custom")
+ {
+ this.CustomServer.Select();
+ }
+ this.Slider.YBounds.max = this.ScrollStartArea.y;
+ this.Slider.YBounds.min = scrollStartArea.y;
+ }
+
+ internal void SelectServer(ServerSelector selected)
+ {
+ for (int i = 0; i < this.myButtons.Count; i++)
+ {
+ ServerSelector serverSelector = this.myButtons[i];
+ if (!serverSelector.MyServer.Default)
+ {
+ serverSelector.Unselect();
+ }
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/ServerSelector.cs b/Client/Assembly-CSharp/ServerSelector.cs
new file mode 100644
index 0000000..b29aa30
--- /dev/null
+++ b/Client/Assembly-CSharp/ServerSelector.cs
@@ -0,0 +1,53 @@
+using System;
+using System.Net;
+using UnityEngine;
+using UnityEngine.Events;
+
+public class ServerSelector : MonoBehaviour
+{
+ public ServerSelectUi Parent { get; set; }
+
+ public ServerInfo MyServer = new ServerInfo();
+
+ public TextRenderer Text;
+
+ public ButtonRolloverHandler Background;
+
+ public TextBox ipInput;
+
+ public void Start()
+ {
+ if (this.ipInput)
+ {
+ this.ipInput.SetText(this.MyServer.Ip, "");
+ this.ipInput.OnChange.AddListener(new UnityAction(this.OnIpChange));
+ return;
+ }
+ this.Text.Text = this.MyServer.Name;
+ }
+
+ private void OnIpChange()
+ {
+ IPAddress ipaddress;
+ if (!IPAddress.TryParse(this.ipInput.text, out ipaddress))
+ {
+ return;
+ }
+ this.MyServer.Name = "Custom";
+ this.MyServer.Ip = this.ipInput.text;
+ this.Select();
+ }
+
+ public void Select()
+ {
+ this.Background.OutColor = Color.green;
+ this.Background.DoMouseOut();
+ this.Parent.SelectServer(this);
+ }
+
+ internal void Unselect()
+ {
+ this.Background.OutColor = Color.white;
+ this.Background.DoMouseOut();
+ }
+}
diff --git a/Client/Assembly-CSharp/SettingsMode.cs b/Client/Assembly-CSharp/SettingsMode.cs
new file mode 100644
index 0000000..48c138b
--- /dev/null
+++ b/Client/Assembly-CSharp/SettingsMode.cs
@@ -0,0 +1,7 @@
+using System;
+
+public enum SettingsMode
+{
+ Host,
+ Search
+}
diff --git a/Client/Assembly-CSharp/ShadowCamera.cs b/Client/Assembly-CSharp/ShadowCamera.cs
new file mode 100644
index 0000000..468d259
--- /dev/null
+++ b/Client/Assembly-CSharp/ShadowCamera.cs
@@ -0,0 +1,17 @@
+using System;
+using UnityEngine;
+
+public class ShadowCamera : MonoBehaviour
+{
+ public Shader Shadozer;
+
+ public void OnEnable()
+ {
+ base.GetComponent<Camera>().SetReplacementShader(this.Shadozer, "RenderType");
+ }
+
+ public void OnDisable()
+ {
+ base.GetComponent<Camera>().ResetReplacementShader();
+ }
+}
diff --git a/Client/Assembly-CSharp/ShhhBehaviour.cs b/Client/Assembly-CSharp/ShhhBehaviour.cs
new file mode 100644
index 0000000..6164c57
--- /dev/null
+++ b/Client/Assembly-CSharp/ShhhBehaviour.cs
@@ -0,0 +1,135 @@
+using System;
+using System.Collections;
+using UnityEngine;
+
+public class ShhhBehaviour : MonoBehaviour
+{
+ public SpriteRenderer Background;
+
+ public SpriteRenderer Body;
+
+ public SpriteRenderer Hand;
+
+ public SpriteRenderer TextImage;
+
+ public float RotateSpeed = 15f;
+
+ public Vector2Range HandTarget;
+
+ public AnimationCurve PositionEasing;
+
+ public FloatRange HandRotate;
+
+ public AnimationCurve RotationEasing;
+
+ public Vector2Range TextTarget;
+
+ public AnimationCurve TextEasing;
+
+ public float Duration = 0.5f;
+
+ public float Delay = 0.1f;
+
+ public float TextDuration = 0.5f;
+
+ public float PulseDuration = 0.1f;
+
+ public float PulseSize = 0.1f;
+
+ public float HoldDuration = 2f;
+
+ public bool Autoplay;
+
+ public void OnEnable()
+ {
+ if (this.Autoplay)
+ {
+ Vector3 localScale = default(Vector3);
+ this.UpdateHand(ref localScale, 1f);
+ this.UpdateText(ref localScale, 1f);
+ localScale.Set(1f, 1f, 1f);
+ this.Body.transform.localScale = localScale;
+ this.TextImage.color = Color.white;
+ }
+ }
+
+ public IEnumerator PlayAnimation()
+ {
+ base.StartCoroutine(this.AnimateHand());
+ yield return this.AnimateText();
+ yield return ShhhBehaviour.WaitWithInterrupt(this.HoldDuration);
+ yield break;
+ }
+
+ public void Update()
+ {
+ this.Background.transform.Rotate(0f, 0f, Time.deltaTime * this.RotateSpeed);
+ }
+
+ private IEnumerator AnimateText()
+ {
+ this.TextImage.color = Palette.ClearWhite;
+ for (float t = 0f; t < this.Delay; t += Time.deltaTime)
+ {
+ yield return null;
+ }
+ Vector3 vec = default(Vector3);
+ for (float t = 0f; t < this.PulseDuration; t += Time.deltaTime)
+ {
+ float num = t / this.PulseDuration;
+ float num2 = 1f + Mathf.Sin(3.1415927f * num) * this.PulseSize;
+ vec.Set(num2, num2, 1f);
+ this.Body.transform.localScale = vec;
+ this.TextImage.color = Color.Lerp(Palette.ClearWhite, Palette.White, num * 2f);
+ yield return null;
+ }
+ vec.Set(1f, 1f, 1f);
+ this.Body.transform.localScale = vec;
+ this.TextImage.color = Color.white;
+ yield break;
+ }
+
+ private IEnumerator AnimateHand()
+ {
+ this.Hand.transform.localPosition = this.HandTarget.min;
+ Vector3 vec = default(Vector3);
+ for (float t = 0f; t < this.Duration; t += Time.deltaTime)
+ {
+ float p = t / this.Duration;
+ this.UpdateHand(ref vec, p);
+ yield return null;
+ }
+ this.UpdateHand(ref vec, 1f);
+ yield break;
+ }
+
+ private void UpdateHand(ref Vector3 vec, float p)
+ {
+ this.HandTarget.LerpUnclamped(ref vec, this.PositionEasing.Evaluate(p), -1f);
+ this.Hand.transform.localPosition = vec;
+ vec.Set(0f, 0f, this.HandRotate.LerpUnclamped(this.RotationEasing.Evaluate(p)));
+ this.Hand.transform.eulerAngles = vec;
+ }
+
+ private void UpdateText(ref Vector3 vec, float p)
+ {
+ this.TextTarget.LerpUnclamped(ref vec, p, -2f);
+ this.TextImage.transform.localPosition = vec;
+ }
+
+ public static IEnumerator WaitWithInterrupt(float duration)
+ {
+ float timer = 0f;
+ while (timer < duration && !ShhhBehaviour.CheckForInterrupt())
+ {
+ yield return null;
+ timer += Time.deltaTime;
+ }
+ yield break;
+ }
+
+ public static bool CheckForInterrupt()
+ {
+ return Input.anyKeyDown;
+ }
+}
diff --git a/Client/Assembly-CSharp/ShieldMinigame.cs b/Client/Assembly-CSharp/ShieldMinigame.cs
new file mode 100644
index 0000000..553c5fa
--- /dev/null
+++ b/Client/Assembly-CSharp/ShieldMinigame.cs
@@ -0,0 +1,84 @@
+using System;
+using UnityEngine;
+
+public class ShieldMinigame : Minigame
+{
+ public Color OnColor = Color.white;
+
+ public Color OffColor = Color.red;
+
+ public SpriteRenderer[] Shields;
+
+ public SpriteRenderer Gauge;
+
+ private byte shields;
+
+ public AudioClip ShieldOnSound;
+
+ public AudioClip ShieldOffSound;
+
+ public override void Begin(PlayerTask task)
+ {
+ base.Begin(task);
+ this.shields = this.MyNormTask.Data[0];
+ this.UpdateButtons();
+ }
+
+ public void ToggleShield(int i)
+ {
+ if (!this.MyNormTask.IsComplete)
+ {
+ byte b = (byte)(1 << i);
+ this.shields ^= b;
+ this.MyNormTask.Data[0] = this.shields;
+ if ((this.shields & b) != 0)
+ {
+ if (Constants.ShouldPlaySfx())
+ {
+ SoundManager.Instance.PlaySound(this.ShieldOnSound, false, 1f);
+ }
+ }
+ else if (Constants.ShouldPlaySfx())
+ {
+ SoundManager.Instance.PlaySound(this.ShieldOffSound, false, 1f);
+ }
+ if (this.shields == 127)
+ {
+ this.MyNormTask.NextStep();
+ base.StartCoroutine(base.CoStartClose(0.75f));
+ if (!ShipStatus.Instance.ShieldsImages[0].IsPlaying(null))
+ {
+ ShipStatus.Instance.StartShields();
+ PlayerControl.LocalPlayer.RpcPlayAnimation(1);
+ }
+ }
+ }
+ }
+
+ public void FixedUpdate()
+ {
+ this.UpdateButtons();
+ }
+
+ private void UpdateButtons()
+ {
+ int num = 0;
+ for (int i = 0; i < this.Shields.Length; i++)
+ {
+ bool flag = ((int)this.shields & 1 << i) == 0;
+ if (!flag)
+ {
+ num++;
+ }
+ this.Shields[i].color = (flag ? this.OffColor : this.OnColor);
+ }
+ if (this.shields == 127)
+ {
+ this.Gauge.transform.Rotate(0f, 0f, Time.fixedDeltaTime * 45f);
+ this.Gauge.color = new Color(1f, 1f, 1f, 1f);
+ return;
+ }
+ float num2 = Mathf.Lerp(0.1f, 0.5f, (float)num / 6f);
+ this.Gauge.color = new Color(1f, num2, num2, 1f);
+ }
+}
diff --git a/Client/Assembly-CSharp/ShipRoom.cs b/Client/Assembly-CSharp/ShipRoom.cs
new file mode 100644
index 0000000..8dae7a6
--- /dev/null
+++ b/Client/Assembly-CSharp/ShipRoom.cs
@@ -0,0 +1,15 @@
+using System;
+using UnityEngine;
+
+public class ShipRoom : MonoBehaviour
+{
+ public SystemTypes RoomId;
+
+ public SurvCamera survCamera;
+
+ public Collider2D roomArea;
+
+ public AudioClip AmbientSound;
+
+ public SoundGroup FootStepSounds;
+}
diff --git a/Client/Assembly-CSharp/ShipStatus.cs b/Client/Assembly-CSharp/ShipStatus.cs
new file mode 100644
index 0000000..81d8b4a
--- /dev/null
+++ b/Client/Assembly-CSharp/ShipStatus.cs
@@ -0,0 +1,738 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Assets.CoreScripts;
+using Hazel;
+using InnerNet;
+using PowerTools;
+using UnityEngine;
+
+//场景中的物件,包含门的开启等,在这里同步
+public class ShipStatus : InnerNetObject
+{
+ public ShipRoom[] AllRooms { get; private set; }
+
+ public Vent[] AllVents { get; private set; }
+
+ public static ShipStatus Instance;
+
+ public Color CameraColor = Color.black;
+
+ public float MaxLightRadius = 100f;
+
+ public float MinLightRadius;
+
+ public float MapScale = 4.4f;
+
+ public Vector2 MapOffset = new Vector2(0.54f, 1.25f);
+
+ public MapBehaviour MapPrefab;
+
+ public Transform SpawnCenter;
+
+ public float SpawnRadius = 1.55f;
+
+ public AudioClip shipHum;
+
+ public NormalPlayerTask[] CommonTasks;
+
+ public NormalPlayerTask[] LongTasks;
+
+ public NormalPlayerTask[] NormalTasks;
+
+ public PlayerTask[] SpecialTasks;
+
+ public AutoOpenDoor[] AllDoors;
+
+ public global::Console[] AllConsoles;
+
+ //c 场景中的门、反应堆等物件的状态
+ public Dictionary<SystemTypes, ISystemType> Systems;
+
+ public AnimationClip[] WeaponFires;
+
+ public SpriteAnim WeaponsImage;
+
+ public AnimationClip HatchActive;
+
+ public SpriteAnim Hatch;
+
+ public ParticleSystem HatchParticles;
+
+ public AnimationClip ShieldsActive;
+
+ public SpriteAnim[] ShieldsImages;
+
+ public SpriteRenderer ShieldBorder;
+
+ public Sprite ShieldBorderOn;
+
+ public SpriteRenderer MedScanner;
+
+ private int WeaponFireIdx;
+
+ public float Timer;
+
+ public float EmergencyCooldown;
+
+ private RaycastHit2D[] volumeBuffer = new RaycastHit2D[5];
+
+ public class SystemTypeComparer : IEqualityComparer<SystemTypes>
+ {
+ public static readonly ShipStatus.SystemTypeComparer Instance = new ShipStatus.SystemTypeComparer();
+
+ public bool Equals(SystemTypes x, SystemTypes y)
+ {
+ return x == y;
+ }
+
+ public int GetHashCode(SystemTypes obj)
+ {
+ return (int)obj;
+ }
+ }
+
+ private enum RpcCalls
+ {
+ CloseDoorsOfType,
+ RepairSystem
+ }
+
+ public ShipStatus()
+ {
+ //c 所有的systems
+ this.Systems = new Dictionary<SystemTypes, ISystemType>(ShipStatus.SystemTypeComparer.Instance)
+ {
+ {
+ SystemTypes.Electrical,
+ new SwitchSystem()
+ },
+ {
+ SystemTypes.MedBay,
+ new MedScanSystem()
+ },
+ {
+ SystemTypes.Reactor,
+ new ReactorSystemType()
+ },
+ {
+ SystemTypes.LifeSupp,
+ new LifeSuppSystemType()
+ },
+ {
+ SystemTypes.Security,
+ new SecurityCameraSystemType()
+ },
+ {
+ SystemTypes.Comms,
+ new HudOverrideSystemType()
+ },
+ {
+ SystemTypes.Doors,
+ new DoorsSystemType()
+ }
+ };
+ this.Systems.Add(SystemTypes.Sabotage, new SabotageSystemType(new IActivatable[]
+ {
+ (IActivatable)this.Systems[SystemTypes.Comms],
+ (IActivatable)this.Systems[SystemTypes.Reactor],
+ (IActivatable)this.Systems[SystemTypes.LifeSupp],
+ (IActivatable)this.Systems[SystemTypes.Electrical]
+ }));
+ }
+
+ private void Awake()
+ {
+ this.AllRooms = base.GetComponentsInChildren<ShipRoom>();
+ this.AllConsoles = base.GetComponentsInChildren<global::Console>();
+ this.AllVents = base.GetComponentsInChildren<Vent>();
+ this.AssignTaskIndexes();
+ ShipStatus.Instance = this;
+ }
+
+ public void Start()
+ {
+ Camera.main.backgroundColor = this.CameraColor;
+ if (DestroyableSingleton<HudManager>.InstanceExists)
+ {
+ DestroyableSingleton<HudManager>.Instance.Chat.ForceClosed();
+ DestroyableSingleton<HudManager>.Instance.Chat.SetVisible(false);
+ DestroyableSingleton<HudManager>.Instance.GameSettings.gameObject.SetActive(false);
+ }
+ DeconSystem componentInChildren = base.GetComponentInChildren<DeconSystem>();
+ if (componentInChildren)
+ {
+ this.Systems.Add(SystemTypes.Decontamination, componentInChildren);
+ }
+ SoundManager.Instance.StopAllSound();
+ AudioSource audioSource = SoundManager.Instance.PlaySound(this.shipHum, true, 1f);
+ if (audioSource)
+ {
+ audioSource.pitch = 0.8f;
+ }
+ if (Constants.ShouldPlaySfx())
+ {
+ for (int i = 0; i < this.AllRooms.Length; i++)
+ {
+ ShipRoom room = this.AllRooms[i];
+ if (room.AmbientSound)
+ {
+ SoundManager.Instance.PlayDynamicSound("Amb " + room.RoomId, room.AmbientSound, true, delegate(AudioSource player, float dt)
+ {
+ this.GetAmbientSoundVolume(room, player, dt);
+ }, false);
+ }
+ }
+ }
+ }
+
+ public override void OnDestroy()
+ {
+ SoundManager.Instance.StopAllSound();
+ base.OnDestroy();
+ }
+
+ public Vector2 GetSpawnLocation(int playerId, int numPlayer)
+ {
+ Vector2 vector = Vector2.up;
+ vector = vector.Rotate((float)(playerId - 1) * (360f / (float)numPlayer));
+ vector *= this.SpawnRadius;
+ return this.SpawnCenter.position + vector + new Vector2(0f, 0.3636f);
+ }
+
+ public void StartShields()
+ {
+ for (int i = 0; i < this.ShieldsImages.Length; i++)
+ {
+ this.ShieldsImages[i].Play(this.ShieldsActive, 1f);
+ }
+ this.ShieldBorder.sprite = this.ShieldBorderOn;
+ }
+
+ public void FireWeapon()
+ {
+ if (!this.WeaponsImage.IsPlaying(null))
+ {
+ this.WeaponsImage.Play(this.WeaponFires[this.WeaponFireIdx], 1f);
+ this.WeaponFireIdx = (this.WeaponFireIdx + 1) % 2;
+ }
+ }
+
+ public NormalPlayerTask GetTaskById(byte idx)
+ {
+ NormalPlayerTask result;
+ if ((result = this.CommonTasks.FirstOrDefault((NormalPlayerTask t) => t.Index == (int)idx)) == null)
+ {
+ result = (this.LongTasks.FirstOrDefault((NormalPlayerTask t) => t.Index == (int)idx) ?? this.NormalTasks.FirstOrDefault((NormalPlayerTask t) => t.Index == (int)idx));
+ }
+ return result;
+ }
+
+ public void OpenHatch()
+ {
+ if (!this.Hatch.IsPlaying(null))
+ {
+ this.Hatch.Play(this.HatchActive, 1f);
+ this.HatchParticles.Play();
+ }
+ }
+
+ public void CloseDoorsOfType(SystemTypes room)
+ {
+ (this.Systems[SystemTypes.Doors] as DoorsSystemType).CloseDoorsOfType(room);
+ base.SetDirtyBit(65536U);
+ }
+
+ public void RepairSystem(SystemTypes systemType, PlayerControl player, byte amount)
+ {
+ this.Systems[systemType].RepairDamage(player, amount);
+ base.SetDirtyBit(1U << (int)systemType);
+ }
+
+ internal void SelectInfected()
+ {
+ List<GameData.PlayerInfo> list = (from pcd in GameData.Instance.AllPlayers
+ where !pcd.Disconnected
+ select pcd into pc
+ where !pc.IsDead
+ select pc).ToList<GameData.PlayerInfo>();
+ int adjustedNumImpostors = PlayerControl.GameOptions.GetAdjustedNumImpostors(GameData.Instance.PlayerCount);
+ list.RemoveDupes<GameData.PlayerInfo>();
+ GameData.PlayerInfo[] array = new GameData.PlayerInfo[Mathf.Min(list.Count, adjustedNumImpostors)];
+ for (int i = 0; i < array.Length; i++)
+ {
+ int index = HashRandom.FastNext(list.Count);
+ array[i] = list[index];
+ list.RemoveAt(index);
+ }
+ foreach (GameData.PlayerInfo playerInfo in array)
+ {
+ DestroyableSingleton<Telemetry>.Instance.SelectInfected((int)playerInfo.ColorId, playerInfo.HatId);
+ }
+ PlayerControl.LocalPlayer.RpcSetInfected(array);
+ }
+
+ private void AssignTaskIndexes()
+ {
+ int num = 0;
+ for (int i = 0; i < this.CommonTasks.Length; i++)
+ {
+ this.CommonTasks[i].Index = num++;
+ }
+ for (int j = 0; j < this.LongTasks.Length; j++)
+ {
+ this.LongTasks[j].Index = num++;
+ }
+ for (int k = 0; k < this.NormalTasks.Length; k++)
+ {
+ this.NormalTasks[k].Index = num++;
+ }
+ }
+
+ public void Begin()
+ {
+ this.AssignTaskIndexes();
+ GameOptionsData gameOptions = PlayerControl.GameOptions;
+ List<GameData.PlayerInfo> allPlayers = GameData.Instance.AllPlayers;
+ HashSet<TaskTypes> hashSet = new HashSet<TaskTypes>();
+ List<byte> list = new List<byte>(10);
+ List<NormalPlayerTask> list2 = this.CommonTasks.ToList<NormalPlayerTask>();
+ list2.Shuffle<NormalPlayerTask>();
+ int num = 0;
+ this.AddTasksFromList(ref num, gameOptions.NumCommonTasks, list, hashSet, list2);
+ for (int i = 0; i < gameOptions.NumCommonTasks; i++)
+ {
+ if (list2.Count == 0)
+ {
+ Debug.LogWarning("Not enough common tasks");
+ break;
+ }
+ int index = list2.RandomIdx<NormalPlayerTask>();
+ list.Add((byte)list2[index].Index);
+ list2.RemoveAt(index);
+ }
+ List<NormalPlayerTask> list3 = this.LongTasks.ToList<NormalPlayerTask>();
+ list3.Shuffle<NormalPlayerTask>();
+ List<NormalPlayerTask> list4 = this.NormalTasks.ToList<NormalPlayerTask>();
+ list4.Shuffle<NormalPlayerTask>();
+ int num2 = 0;
+ int num3 = 0;
+ int count = gameOptions.NumShortTasks;
+ if (gameOptions.NumCommonTasks + gameOptions.NumLongTasks + gameOptions.NumShortTasks == 0)
+ {
+ count = 1;
+ }
+ byte b = 0;
+ while ((int)b < allPlayers.Count)
+ {
+ hashSet.Clear();
+ list.RemoveRange(gameOptions.NumCommonTasks, list.Count - gameOptions.NumCommonTasks);
+ this.AddTasksFromList(ref num2, gameOptions.NumLongTasks, list, hashSet, list3);
+ this.AddTasksFromList(ref num3, count, list, hashSet, list4);
+ GameData.PlayerInfo playerInfo = allPlayers[(int)b];
+ if (playerInfo.Object && !playerInfo.Object.GetComponent<DummyBehaviour>().enabled)
+ {
+ byte[] taskTypeIds = list.ToArray();
+ GameData.Instance.RpcSetTasks(playerInfo.PlayerId, taskTypeIds);
+ }
+ b += 1;
+ }
+ base.enabled = true;
+ }
+
+ private void AddTasksFromList(ref int start, int count, List<byte> tasks, HashSet<TaskTypes> usedTaskTypes, List<NormalPlayerTask> unusedTasks)
+ {
+ int num = 0;
+ int num2 = 0;
+ Func<NormalPlayerTask, bool> <>9__0;
+ while (num2 < count && num++ != 1000)
+ {
+ if (start >= unusedTasks.Count)
+ {
+ start = 0;
+ unusedTasks.Shuffle<NormalPlayerTask>();
+ Func<NormalPlayerTask, bool> predicate;
+ if ((predicate = <>9__0) == null)
+ {
+ predicate = (<>9__0 = ((NormalPlayerTask t) => usedTaskTypes.Contains(t.TaskType)));
+ }
+ if (unusedTasks.All(predicate))
+ {
+ Debug.Log("Not enough task types");
+ usedTaskTypes.Clear();
+ }
+ }
+ int num3 = start;
+ start = num3 + 1;
+ NormalPlayerTask normalPlayerTask = unusedTasks[num3];
+ if (!usedTaskTypes.Add(normalPlayerTask.TaskType))
+ {
+ num2--;
+ }
+ else
+ {
+ tasks.Add((byte)normalPlayerTask.Index);
+ }
+ num2++;
+ }
+ }
+
+ public void FixedUpdate()
+ {
+ if (!AmongUsClient.Instance)
+ {
+ return;
+ }
+ this.Timer += Time.fixedDeltaTime;
+ this.EmergencyCooldown -= Time.fixedDeltaTime;
+ if (GameData.Instance)
+ {
+ GameData.Instance.RecomputeTaskCounts();
+ }
+ if (AmongUsClient.Instance.AmHost)
+ {
+ this.CheckEndCriteria();
+ }
+ if (AmongUsClient.Instance.AmClient)
+ {
+ for (int i = 0; i < SystemTypeHelpers.AllTypes.Length; i++)
+ {
+ SystemTypes systemTypes = SystemTypeHelpers.AllTypes[i];
+ ISystemType systemType;
+ if (this.Systems.TryGetValue(systemTypes, out systemType) && systemType.Detoriorate(Time.fixedDeltaTime))
+ {
+ base.SetDirtyBit(1U << (int)systemTypes);
+ }
+ }
+ }
+ }
+
+ private void GetAmbientSoundVolume(ShipRoom room, AudioSource player, float dt)
+ {
+ if (!PlayerControl.LocalPlayer)
+ {
+ player.volume = 0f;
+ return;
+ }
+ Vector2 vector = room.transform.position;
+ Vector2 truePosition = PlayerControl.LocalPlayer.GetTruePosition();
+ float num = Vector2.Distance(vector, truePosition);
+ if (num > 8f)
+ {
+ player.volume = 0f;
+ return;
+ }
+ Vector2 direction = truePosition - vector;
+ int num2 = Physics2D.RaycastNonAlloc(vector, direction, this.volumeBuffer, num, Constants.ShipOnlyMask);
+ float num3 = 1f - num / 8f - (float)num2 * 0.25f;
+ player.volume = Mathf.Lerp(player.volume, num3 * 0.7f, dt);
+ }
+
+ public float CalculateLightRadius(GameData.PlayerInfo player)
+ {
+ if (player.IsDead)
+ {
+ return this.MaxLightRadius;
+ }
+ SwitchSystem switchSystem = (SwitchSystem)this.Systems[SystemTypes.Electrical];
+ if (player.IsImpostor)
+ {
+ return this.MaxLightRadius * PlayerControl.GameOptions.ImpostorLightMod;
+ }
+ float t = (float)switchSystem.Value / 255f;
+ return Mathf.Lerp(this.MinLightRadius, this.MaxLightRadius, t) * PlayerControl.GameOptions.CrewLightMod;
+ }
+
+ //c 序列化所有物件的状态
+ public override bool Serialize(MessageWriter writer, bool initialState)
+ {
+ if (initialState)
+ {
+ (this.Systems[SystemTypes.Doors] as DoorsSystemType).SetDoors(this.AllDoors);
+ short num = 0;
+ while ((int)num < SystemTypeHelpers.AllTypes.Length)
+ {
+ SystemTypes key = SystemTypeHelpers.AllTypes[(int)num];
+ ISystemType systemType;
+ if (this.Systems.TryGetValue(key, out systemType))
+ {
+ systemType.Serialize(writer, true);
+ }
+ num += 1;
+ }
+ return true;
+ }
+ if (this.DirtyBits != 0U)
+ {
+ writer.WritePacked(this.DirtyBits);
+ short num2 = 0;
+ while ((int)num2 < SystemTypeHelpers.AllTypes.Length)
+ {
+ SystemTypes systemTypes = SystemTypeHelpers.AllTypes[(int)num2];
+ ISystemType systemType2;
+ if (((ulong)this.DirtyBits & (ulong)(1L << (int)(systemTypes & (SystemTypes)31))) != 0UL && this.Systems.TryGetValue(systemTypes, out systemType2))
+ {
+ systemType2.Serialize(writer, false);
+ }
+ num2 += 1;
+ }
+ this.DirtyBits = 0U;
+ return true;
+ }
+ return false;
+ }
+
+ public override void Deserialize(MessageReader reader, bool initialState)
+ {
+ if (initialState)
+ {
+ (this.Systems[SystemTypes.Doors] as DoorsSystemType).SetDoors(this.AllDoors);
+ short num = 0;
+ while ((int)num < SystemTypeHelpers.AllTypes.Length)
+ {
+ SystemTypes key = (SystemTypes)num;
+ ISystemType systemType;
+ if (this.Systems.TryGetValue(key, out systemType))
+ {
+ systemType.Deserialize(reader, true);
+ }
+ num += 1;
+ }
+ return;
+ }
+ uint num2 = reader.ReadPackedUInt32();
+ short num3 = 0;
+ while ((int)num3 < SystemTypeHelpers.AllTypes.Length)
+ {
+ SystemTypes systemTypes = SystemTypeHelpers.AllTypes[(int)num3];
+ ISystemType systemType2;
+ if (((ulong)num2 & (ulong)(1L << (int)(systemTypes & (SystemTypes)31))) != 0UL && this.Systems.TryGetValue(systemTypes, out systemType2))
+ {
+ systemType2.Deserialize(reader, false);
+ }
+ num3 += 1;
+ }
+ }
+
+ private void CheckEndCriteria()
+ {
+ if (!GameData.Instance)
+ {
+ return;
+ }
+ LifeSuppSystemType lifeSuppSystemType = (LifeSuppSystemType)this.Systems[SystemTypes.LifeSupp];
+ if (lifeSuppSystemType.Countdown < 0f)
+ {
+ this.EndGameForSabotage();
+ lifeSuppSystemType.Countdown = 10000f;
+ }
+ ReactorSystemType reactorSystemType = (ReactorSystemType)this.Systems[SystemTypes.Reactor];
+ if (reactorSystemType.Countdown < 0f)
+ {
+ this.EndGameForSabotage();
+ reactorSystemType.Countdown = 10000f;
+ }
+ int num = 0;
+ int num2 = 0;
+ int num3 = 0;
+ for (int i = 0; i < GameData.Instance.PlayerCount; i++)
+ {
+ GameData.PlayerInfo playerInfo = GameData.Instance.AllPlayers[i];
+ if (!playerInfo.Disconnected)
+ {
+ if (playerInfo.IsImpostor)
+ {
+ num3++;
+ }
+ if (!playerInfo.IsDead)
+ {
+ if (playerInfo.IsImpostor)
+ {
+ num2++;
+ }
+ else
+ {
+ num++;
+ }
+ }
+ }
+ }
+ if (num2 <= 0 && (!DestroyableSingleton<TutorialManager>.InstanceExists || num3 > 0))
+ {
+ if (!DestroyableSingleton<TutorialManager>.InstanceExists)
+ {
+ base.enabled = false;
+ ShipStatus.RpcEndGame((TempData.LastDeathReason == DeathReason.Disconnect) ? GameOverReason.ImpostorDisconnect : GameOverReason.HumansByVote, !SaveManager.BoughtNoAds);
+ return;
+ }
+ DestroyableSingleton<HudManager>.Instance.ShowPopUp("Normally The Crew would have just won because The Impostor is dead. For free play, we revive everyone instead.");
+ ShipStatus.ReviveEveryone();
+ return;
+ }
+ else
+ {
+ if (num > num2)
+ {
+ if (!DestroyableSingleton<TutorialManager>.InstanceExists)
+ {
+ if (GameData.Instance.TotalTasks <= GameData.Instance.CompletedTasks)
+ {
+ base.enabled = false;
+ ShipStatus.RpcEndGame(GameOverReason.HumansByTask, !SaveManager.BoughtNoAds);
+ return;
+ }
+ }
+ else if (PlayerControl.LocalPlayer.myTasks.All((PlayerTask t) => t.IsComplete))
+ {
+ DestroyableSingleton<HudManager>.Instance.ShowPopUp("Normally The Crew would have just won because the task bar is full. For free play, we issue new tasks instead.");
+ this.Begin();
+ }
+ return;
+ }
+ if (!DestroyableSingleton<TutorialManager>.InstanceExists)
+ {
+ base.enabled = false;
+ GameOverReason endReason;
+ switch (TempData.LastDeathReason)
+ {
+ case DeathReason.Exile:
+ endReason = GameOverReason.ImpostorByVote;
+ break;
+ case DeathReason.Kill:
+ endReason = GameOverReason.ImpostorByKill;
+ break;
+ default:
+ endReason = GameOverReason.HumansDisconnect;
+ break;
+ }
+ ShipStatus.RpcEndGame(endReason, !SaveManager.BoughtNoAds);
+ return;
+ }
+ DestroyableSingleton<HudManager>.Instance.ShowPopUp("Normally The Impostor would have just won because The Crew can no longer win. For free play, we revive everyone instead.");
+ ShipStatus.ReviveEveryone();
+ return;
+ }
+ }
+
+ private void EndGameForSabotage()
+ {
+ if (!DestroyableSingleton<TutorialManager>.InstanceExists)
+ {
+ base.enabled = false;
+ ShipStatus.RpcEndGame(GameOverReason.ImpostorBySabotage, !SaveManager.BoughtNoAds);
+ return;
+ }
+ DestroyableSingleton<HudManager>.Instance.ShowPopUp("Normally The Impostor would have just won because of the critical sabotage. Instead we just shut it off.");
+ }
+
+ public bool IsGameOverDueToDeath()
+ {
+ int num = 0;
+ int num2 = 0;
+ int num3 = 0;
+ for (int i = 0; i < GameData.Instance.PlayerCount; i++)
+ {
+ GameData.PlayerInfo playerInfo = GameData.Instance.AllPlayers[i];
+ if (!playerInfo.Disconnected)
+ {
+ if (playerInfo.IsImpostor)
+ {
+ num3++;
+ }
+ if (!playerInfo.IsDead)
+ {
+ if (playerInfo.IsImpostor)
+ {
+ num2++;
+ }
+ else
+ {
+ num++;
+ }
+ }
+ }
+ }
+ return (num2 <= 0 && (!DestroyableSingleton<TutorialManager>.InstanceExists || num3 > 0)) || num <= num2;
+ }
+
+ private static void RpcEndGame(GameOverReason endReason, bool showAd)
+ {
+ MessageWriter messageWriter = AmongUsClient.Instance.StartEndGame();
+ messageWriter.Write((byte)endReason);
+ messageWriter.Write(showAd);
+ AmongUsClient.Instance.FinishEndGame(messageWriter);
+ }
+
+ private static void ReviveEveryone()
+ {
+ for (int i = 0; i < GameData.Instance.PlayerCount; i++)
+ {
+ GameData.Instance.AllPlayers[i].Object.Revive();
+ }
+ UnityEngine.Object.FindObjectsOfType<DeadBody>().ForEach(delegate(DeadBody b)
+ {
+ UnityEngine.Object.Destroy(b.gameObject);
+ });
+ }
+
+ public bool CheckTaskCompletion()
+ {
+ if (DestroyableSingleton<TutorialManager>.InstanceExists)
+ {
+ if (PlayerControl.LocalPlayer.myTasks.All((PlayerTask t) => t.IsComplete))
+ {
+ DestroyableSingleton<HudManager>.Instance.ShowPopUp("Normally The Crew would have just won because the task bar is full. For free play, we issue new tasks instead.");
+ this.Begin();
+ }
+ return false;
+ }
+ GameData.Instance.RecomputeTaskCounts();
+ if (GameData.Instance.TotalTasks <= GameData.Instance.CompletedTasks)
+ {
+ base.enabled = false;
+ ShipStatus.RpcEndGame(GameOverReason.HumansByTask, !SaveManager.BoughtNoAds);
+ return true;
+ }
+ return false;
+ }
+
+ public void RpcCloseDoorsOfType(SystemTypes type)
+ {
+ if (AmongUsClient.Instance.AmHost)
+ {
+ this.CloseDoorsOfType(type);
+ return;
+ }
+ MessageWriter messageWriter = AmongUsClient.Instance.StartRpcImmediately(this.NetId, 0, SendOption.Reliable, AmongUsClient.Instance.HostId);
+ messageWriter.Write((byte)type);
+ AmongUsClient.Instance.FinishRpcImmediately(messageWriter);
+ }
+
+ public void RpcRepairSystem(SystemTypes systemType, int amount)
+ {
+ if (AmongUsClient.Instance.AmHost)
+ {
+ this.RepairSystem(systemType, PlayerControl.LocalPlayer, (byte)amount);
+ return;
+ }
+ MessageWriter messageWriter = AmongUsClient.Instance.StartRpcImmediately(this.NetId, 1, SendOption.Reliable, AmongUsClient.Instance.HostId);
+ messageWriter.Write((byte)systemType);
+ messageWriter.WriteNetObject(PlayerControl.LocalPlayer);
+ messageWriter.Write((byte)amount);
+ AmongUsClient.Instance.FinishRpcImmediately(messageWriter);
+ }
+
+ public override void HandleRpc(byte callId, MessageReader reader)
+ {
+ if (callId == 0)
+ {
+ this.CloseDoorsOfType((SystemTypes)reader.ReadByte());
+ return;
+ }
+ if (callId != 1)
+ {
+ return;
+ }
+ this.RepairSystem((SystemTypes)reader.ReadByte(), reader.ReadNetObject<PlayerControl>(), reader.ReadByte());
+ }
+}
diff --git a/Client/Assembly-CSharp/ShowAdsState.cs b/Client/Assembly-CSharp/ShowAdsState.cs
new file mode 100644
index 0000000..3515783
--- /dev/null
+++ b/Client/Assembly-CSharp/ShowAdsState.cs
@@ -0,0 +1,9 @@
+using System;
+
+public enum ShowAdsState : byte
+{
+ Personalized,
+ Accepted = 128,
+ NonPersonalized = 1,
+ Purchased = 130
+}
diff --git a/Client/Assembly-CSharp/SimonSaysGame.cs b/Client/Assembly-CSharp/SimonSaysGame.cs
new file mode 100644
index 0000000..a66114f
--- /dev/null
+++ b/Client/Assembly-CSharp/SimonSaysGame.cs
@@ -0,0 +1,243 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class SimonSaysGame : Minigame
+{
+ private int IndexCount
+ {
+ get
+ {
+ return (int)this.MyNormTask.Data[0];
+ }
+ set
+ {
+ this.MyNormTask.Data[0] = (byte)value;
+ }
+ }
+
+ private byte this[int idx]
+ {
+ get
+ {
+ return this.MyNormTask.Data[idx + 1];
+ }
+ set
+ {
+ this.MyNormTask.Data[idx + 1] = value;
+ }
+ }
+
+ private Queue<int> operations = new Queue<int>();
+
+ private const int FlashOp = 256;
+
+ private const int AnimateOp = 128;
+
+ private const int ReAnimateOp = 32;
+
+ private const int FailOp = 64;
+
+ private Color gray = new Color32(141, 141, 141, byte.MaxValue);
+
+ private Color blue = new Color32(68, 168, byte.MaxValue, byte.MaxValue);
+
+ private Color red = new Color32(byte.MaxValue, 58, 0, byte.MaxValue);
+
+ private Color green = Color.green;
+
+ public SpriteRenderer[] LeftSide;
+
+ public SpriteRenderer[] Buttons;
+
+ public SpriteRenderer[] LeftLights;
+
+ public SpriteRenderer[] RightLights;
+
+ private float flashTime = 0.25f;
+
+ private float userButtonFlashTime = 0.175f;
+
+ public AudioClip ButtonPressSound;
+
+ public AudioClip FailSound;
+
+ public override void Begin(PlayerTask task)
+ {
+ for (int i = 0; i < this.LeftSide.Length; i++)
+ {
+ this.LeftSide[i].color = Color.clear;
+ }
+ base.Begin(task);
+ if (this.IndexCount == 0)
+ {
+ this.operations.Enqueue(128);
+ }
+ else
+ {
+ this.operations.Enqueue(32);
+ }
+ base.StartCoroutine(this.CoRun());
+ }
+
+ public void HitButton(int bIdx)
+ {
+ if (this.MyNormTask.IsComplete || this.MyNormTask.taskStep >= this.IndexCount)
+ {
+ return;
+ }
+ if ((int)this[this.MyNormTask.taskStep] == bIdx)
+ {
+ this.MyNormTask.NextStep();
+ this.SetLights(this.RightLights, this.MyNormTask.taskStep);
+ if (this.MyNormTask.IsComplete)
+ {
+ this.SetLights(this.LeftLights, this.LeftLights.Length);
+ for (int i = 0; i < this.Buttons.Length; i++)
+ {
+ SpriteRenderer spriteRenderer = this.Buttons[i];
+ spriteRenderer.color = this.gray;
+ base.StartCoroutine(this.FlashButton(-1, spriteRenderer, this.flashTime));
+ }
+ base.StartCoroutine(base.CoStartClose(0.75f));
+ return;
+ }
+ this.operations.Enqueue(256 | bIdx);
+ if (this.MyNormTask.taskStep >= this.IndexCount)
+ {
+ this.operations.Enqueue(128);
+ return;
+ }
+ }
+ else
+ {
+ this.IndexCount = 0;
+ this.operations.Enqueue(64);
+ this.operations.Enqueue(128);
+ }
+ }
+
+ private IEnumerator CoRun()
+ {
+ for (;;)
+ {
+ if (this.operations.Count <= 0)
+ {
+ yield return null;
+ }
+ else
+ {
+ int num = this.operations.Dequeue();
+ if (num.HasAnyBit(256))
+ {
+ int num2 = num & -257;
+ yield return this.FlashButton(num2, this.Buttons[num2], this.userButtonFlashTime);
+ }
+ else if (num.HasAnyBit(128))
+ {
+ yield return this.CoAnimateNewLeftSide();
+ }
+ else if (num.HasAnyBit(32))
+ {
+ yield return this.CoAnimateOldLeftSide();
+ }
+ else if (num.HasAnyBit(64))
+ {
+ if (Constants.ShouldPlaySfx())
+ {
+ SoundManager.Instance.PlaySound(this.FailSound, false, 1f);
+ }
+ this.SetAllColor(this.red);
+ yield return new WaitForSeconds(this.flashTime);
+ this.SetAllColor(Color.white);
+ yield return new WaitForSeconds(this.flashTime);
+ this.SetAllColor(this.red);
+ yield return new WaitForSeconds(this.flashTime);
+ this.SetAllColor(Color.white);
+ yield return new WaitForSeconds(this.flashTime / 2f);
+ }
+ }
+ }
+ yield break;
+ }
+
+ private void AddIndex(int idxToAdd)
+ {
+ this[this.IndexCount] = (byte)idxToAdd;
+ int indexCount = this.IndexCount;
+ this.IndexCount = indexCount + 1;
+ }
+
+ private IEnumerator CoAnimateNewLeftSide()
+ {
+ this.SetLights(this.RightLights, 0);
+ for (int i = 0; i < this.Buttons.Length; i++)
+ {
+ this.Buttons[i].color = this.gray;
+ }
+ this.AddIndex(this.Buttons.RandomIdx<SpriteRenderer>());
+ yield return this.CoAnimateOldLeftSide();
+ yield break;
+ }
+
+ private IEnumerator CoAnimateOldLeftSide()
+ {
+ yield return new WaitForSeconds(1f);
+ this.SetLights(this.LeftLights, this.IndexCount);
+ int num2;
+ for (int i = 0; i < this.IndexCount; i = num2)
+ {
+ int num = (int)this[i];
+ yield return this.FlashButton(num, this.LeftSide[num], this.flashTime);
+ yield return new WaitForSeconds(0.1f);
+ num2 = i + 1;
+ }
+ this.MyNormTask.taskStep = 0;
+ for (int j = 0; j < this.Buttons.Length; j++)
+ {
+ this.Buttons[j].color = Color.white;
+ }
+ yield break;
+ }
+
+ private IEnumerator FlashButton(int id, SpriteRenderer butt, float flashTime)
+ {
+ if (id > -1 && Constants.ShouldPlaySfx())
+ {
+ SoundManager.Instance.PlaySound(this.ButtonPressSound, false, 1f).pitch = Mathf.Lerp(0.5f, 1.5f, (float)id / 9f);
+ }
+ Color c = butt.color;
+ butt.color = this.blue;
+ yield return new WaitForSeconds(flashTime);
+ butt.color = c;
+ yield break;
+ }
+
+ private void SetLights(SpriteRenderer[] lights, int num)
+ {
+ for (int i = 0; i < lights.Length; i++)
+ {
+ if (i < num)
+ {
+ lights[i].color = this.green;
+ }
+ else
+ {
+ lights[i].color = this.gray;
+ }
+ }
+ }
+
+ private void SetAllColor(Color color)
+ {
+ for (int i = 0; i < this.Buttons.Length; i++)
+ {
+ this.Buttons[i].color = color;
+ }
+ for (int j = 0; j < this.RightLights.Length; j++)
+ {
+ this.RightLights[j].color = color;
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/SinglePopHelp.cs b/Client/Assembly-CSharp/SinglePopHelp.cs
new file mode 100644
index 0000000..4a8d086
--- /dev/null
+++ b/Client/Assembly-CSharp/SinglePopHelp.cs
@@ -0,0 +1,6 @@
+using System;
+using UnityEngine;
+
+public class SinglePopHelp : MonoBehaviour
+{
+}
diff --git a/Client/Assembly-CSharp/SkinData.cs b/Client/Assembly-CSharp/SkinData.cs
new file mode 100644
index 0000000..0137d23
--- /dev/null
+++ b/Client/Assembly-CSharp/SkinData.cs
@@ -0,0 +1,48 @@
+using System;
+using UnityEngine;
+
+[CreateAssetMenu]
+public class SkinData : ScriptableObject, IBuyable
+{
+ public string ProdId
+ {
+ get
+ {
+ return this.RelatedHat.ProductId;
+ }
+ }
+
+ public Sprite IdleFrame;
+
+ public AnimationClip IdleAnim;
+
+ public AnimationClip RunAnim;
+
+ public AnimationClip EnterVentAnim;
+
+ public AnimationClip ExitVentAnim;
+
+ public AnimationClip KillTongueImpostor;
+
+ public AnimationClip KillTongueVictim;
+
+ public AnimationClip KillShootImpostor;
+
+ public AnimationClip KillShootVictim;
+
+ public AnimationClip KillStabVictim;
+
+ public AnimationClip KillNeckVictim;
+
+ public Sprite EjectFrame;
+
+ public AnimationClip SpawnAnim;
+
+ public bool Free;
+
+ public HatBehaviour RelatedHat;
+
+ public string StoreName;
+
+ public int Order;
+}
diff --git a/Client/Assembly-CSharp/SkinLayer.cs b/Client/Assembly-CSharp/SkinLayer.cs
new file mode 100644
index 0000000..80f0cf6
--- /dev/null
+++ b/Client/Assembly-CSharp/SkinLayer.cs
@@ -0,0 +1,101 @@
+using System;
+using PowerTools;
+using UnityEngine;
+
+public class SkinLayer : MonoBehaviour
+{
+ public bool Flipped
+ {
+ set
+ {
+ this.layer.flipX = value;
+ }
+ }
+
+ public bool Visible
+ {
+ set
+ {
+ this.layer.enabled = value;
+ }
+ }
+
+ public SpriteRenderer layer;
+
+ public SpriteAnim animator;
+
+ public SkinData skin;
+
+ public void SetRun()
+ {
+ if (!this.skin || !this.animator)
+ {
+ this.SetGhost();
+ return;
+ }
+ if (!this.animator.IsPlaying(this.skin.RunAnim))
+ {
+ this.animator.Play(this.skin.RunAnim, 1f);
+ }
+ }
+
+ public void SetSpawn(float time = 0f)
+ {
+ if (!this.skin || !this.animator)
+ {
+ this.SetGhost();
+ return;
+ }
+ this.animator.Play(this.skin.SpawnAnim, 1f);
+ this.animator.Time = time;
+ }
+
+ public void SetExitVent()
+ {
+ if (!this.skin || !this.animator)
+ {
+ this.SetGhost();
+ return;
+ }
+ this.animator.Play(this.skin.ExitVentAnim, 1f);
+ }
+
+ public void SetEnterVent()
+ {
+ if (!this.skin || !this.animator)
+ {
+ this.SetGhost();
+ return;
+ }
+ this.animator.Play(this.skin.EnterVentAnim, 1f);
+ }
+
+ public void SetIdle()
+ {
+ if (!this.skin || !this.animator)
+ {
+ this.SetGhost();
+ return;
+ }
+ if (!this.animator.IsPlaying(this.skin.IdleAnim))
+ {
+ this.animator.Play(this.skin.IdleAnim, 1f);
+ }
+ }
+
+ public void SetGhost()
+ {
+ if (!this.animator)
+ {
+ return;
+ }
+ this.animator.Stop();
+ this.layer.sprite = null;
+ }
+
+ internal void SetSkin(uint skinId)
+ {
+ this.skin = DestroyableSingleton<HatManager>.Instance.GetSkinById(skinId);
+ this.SetIdle();
+ }
+}
diff --git a/Client/Assembly-CSharp/SkinsTab.cs b/Client/Assembly-CSharp/SkinsTab.cs
new file mode 100644
index 0000000..8eecb09
--- /dev/null
+++ b/Client/Assembly-CSharp/SkinsTab.cs
@@ -0,0 +1,83 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class SkinsTab : MonoBehaviour
+{
+ public ColorChip ColorTabPrefab;
+
+ public SpriteRenderer DemoImage;
+
+ public SpriteRenderer HatImage;
+
+ public SpriteRenderer SkinImage;
+
+ public SpriteRenderer PetImage;
+
+ public FloatRange XRange = new FloatRange(1.5f, 3f);
+
+ public float YStart = 0.8f;
+
+ public float YOffset = 0.8f;
+
+ public int NumPerRow = 4;
+
+ public Scroller scroller;
+
+ private List<ColorChip> ColorChips = new List<ColorChip>();
+
+ public void OnEnable()
+ {
+ PlayerControl.SetPlayerMaterialColors((int)PlayerControl.LocalPlayer.Data.ColorId, this.DemoImage);
+ PlayerControl.SetHatImage(SaveManager.LastHat, this.HatImage);
+ PlayerControl.SetSkinImage(SaveManager.LastSkin, this.SkinImage);
+ PlayerControl.SetPetImage(SaveManager.LastPet, (int)PlayerControl.LocalPlayer.Data.ColorId, this.PetImage);
+ SkinData[] unlockedSkins = DestroyableSingleton<HatManager>.Instance.GetUnlockedSkins();
+ for (int i = 0; i < unlockedSkins.Length; i++)
+ {
+ SkinData skin = unlockedSkins[i];
+ float x = this.XRange.Lerp((float)(i % this.NumPerRow) / ((float)this.NumPerRow - 1f));
+ float y = this.YStart - (float)(i / this.NumPerRow) * this.YOffset;
+ ColorChip colorChip = UnityEngine.Object.Instantiate<ColorChip>(this.ColorTabPrefab, this.scroller.Inner);
+ colorChip.transform.localPosition = new Vector3(x, y, -1f);
+ colorChip.Button.OnClick.AddListener(delegate()
+ {
+ this.SelectHat(skin);
+ });
+ colorChip.Inner.sprite = skin.IdleFrame;
+ this.ColorChips.Add(colorChip);
+ }
+ this.scroller.YBounds.max = -(this.YStart - (float)(unlockedSkins.Length / this.NumPerRow) * this.YOffset) - 3f;
+ }
+
+ public void OnDisable()
+ {
+ for (int i = 0; i < this.ColorChips.Count; i++)
+ {
+ UnityEngine.Object.Destroy(this.ColorChips[i].gameObject);
+ }
+ this.ColorChips.Clear();
+ }
+
+ public void Update()
+ {
+ PlayerControl.SetPlayerMaterialColors((int)PlayerControl.LocalPlayer.Data.ColorId, this.DemoImage);
+ SkinData skinById = DestroyableSingleton<HatManager>.Instance.GetSkinById(SaveManager.LastSkin);
+ for (int i = 0; i < this.ColorChips.Count; i++)
+ {
+ ColorChip colorChip = this.ColorChips[i];
+ colorChip.InUseForeground.SetActive(skinById.IdleFrame == colorChip.Inner.sprite);
+ }
+ }
+
+ private void SelectHat(SkinData skin)
+ {
+ uint idFromSkin = DestroyableSingleton<HatManager>.Instance.GetIdFromSkin(skin);
+ SaveManager.LastSkin = idFromSkin;
+ PlayerControl.SetSkinImage(SaveManager.LastSkin, this.SkinImage);
+ if (PlayerControl.LocalPlayer)
+ {
+ PlayerControl.LocalPlayer.RpcSetSkin(idFromSkin);
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/SlideBar.cs b/Client/Assembly-CSharp/SlideBar.cs
new file mode 100644
index 0000000..da36f58
--- /dev/null
+++ b/Client/Assembly-CSharp/SlideBar.cs
@@ -0,0 +1,78 @@
+using System;
+using UnityEngine;
+using UnityEngine.Events;
+
+public class SlideBar : MonoBehaviour
+{
+ public TextRenderer Title;
+
+ public SpriteRenderer Bar;
+
+ public Collider2D HitBox;
+
+ public SpriteRenderer Dot;
+
+ public FloatRange Range;
+
+ public bool Vertical;
+
+ public float Value;
+
+ public UnityEvent OnValueChange;
+
+ public void OnEnable()
+ {
+ if (this.Title)
+ {
+ this.Title.Color = Color.white;
+ }
+ this.Bar.color = Color.white;
+ this.Dot.color = Color.white;
+ }
+
+ public void OnDisable()
+ {
+ if (this.Title)
+ {
+ this.Title.Color = Color.gray;
+ }
+ this.Bar.color = Color.gray;
+ this.Dot.color = Color.gray;
+ }
+
+ public void Update()
+ {
+ Vector3 localPosition = this.Dot.transform.localPosition;
+ switch (DestroyableSingleton<PassiveButtonManager>.Instance.Controller.CheckDrag(this.HitBox, false))
+ {
+ case DragState.Dragging:
+ {
+ Vector2 vector = DestroyableSingleton<PassiveButtonManager>.Instance.Controller.DragPosition - this.Bar.transform.position;
+ if (this.Vertical)
+ {
+ localPosition.y = this.Range.Clamp(vector.y);
+ this.Value = this.Range.ReverseLerp(localPosition.y);
+ }
+ else
+ {
+ localPosition.x = this.Range.Clamp(vector.x);
+ this.Value = this.Range.ReverseLerp(localPosition.x);
+ }
+ this.OnValueChange.Invoke();
+ break;
+ }
+ case DragState.Released:
+ this.OnValueChange.Invoke();
+ break;
+ }
+ if (this.Vertical)
+ {
+ localPosition.y = this.Range.Lerp(this.Value);
+ }
+ else
+ {
+ localPosition.x = this.Range.Lerp(this.Value);
+ }
+ this.Dot.transform.localPosition = localPosition;
+ }
+}
diff --git a/Client/Assembly-CSharp/SortGameObject.cs b/Client/Assembly-CSharp/SortGameObject.cs
new file mode 100644
index 0000000..40a2fc8
--- /dev/null
+++ b/Client/Assembly-CSharp/SortGameObject.cs
@@ -0,0 +1,16 @@
+using System;
+using UnityEngine;
+
+public class SortGameObject : MonoBehaviour
+{
+ public SortGameObject.ObjType MyType;
+
+ public Collider2D Collider;
+
+ public enum ObjType
+ {
+ Plant,
+ Mineral,
+ Animal
+ }
+}
diff --git a/Client/Assembly-CSharp/SortMinigame.cs b/Client/Assembly-CSharp/SortMinigame.cs
new file mode 100644
index 0000000..829f527
--- /dev/null
+++ b/Client/Assembly-CSharp/SortMinigame.cs
@@ -0,0 +1,72 @@
+using System;
+using UnityEngine;
+
+public class SortMinigame : Minigame
+{
+ public SortGameObject[] Objects;
+
+ public BoxCollider2D AnimalBox;
+
+ public BoxCollider2D PlantBox;
+
+ public BoxCollider2D MineralBox;
+
+ private Controller myController = new Controller();
+
+ public void Start()
+ {
+ this.Objects.Shuffle<SortGameObject>();
+ for (int i = 0; i < this.Objects.Length; i++)
+ {
+ this.Objects[i].transform.localPosition = new Vector3(Mathf.Lerp(-2f, 2f, (float)i / ((float)this.Objects.Length - 1f)), FloatRange.Next(-1.75f, -1f), -1f);
+ }
+ }
+
+ public void Update()
+ {
+ if (this.amClosing != Minigame.CloseState.None)
+ {
+ return;
+ }
+ this.myController.Update();
+ for (int i = 0; i < this.Objects.Length; i++)
+ {
+ SortGameObject sortGameObject = this.Objects[i];
+ switch (this.myController.CheckDrag(sortGameObject.Collider, false))
+ {
+ case DragState.Dragging:
+ {
+ Vector2 dragPosition = this.myController.DragPosition;
+ sortGameObject.Collider.attachedRigidbody.position = dragPosition;
+ break;
+ }
+ case DragState.Released:
+ {
+ bool flag = true;
+ for (int j = 0; j < this.Objects.Length; j++)
+ {
+ SortGameObject sortGameObject2 = this.Objects[j];
+ switch (sortGameObject2.MyType)
+ {
+ case SortGameObject.ObjType.Plant:
+ flag &= sortGameObject2.Collider.IsTouching(this.PlantBox);
+ break;
+ case SortGameObject.ObjType.Mineral:
+ flag &= sortGameObject2.Collider.IsTouching(this.MineralBox);
+ break;
+ case SortGameObject.ObjType.Animal:
+ flag &= sortGameObject2.Collider.IsTouching(this.AnimalBox);
+ break;
+ }
+ }
+ if (flag)
+ {
+ this.MyTask.Complete();
+ base.StartCoroutine(base.CoStartClose(0.75f));
+ }
+ break;
+ }
+ }
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/SoundGroup.cs b/Client/Assembly-CSharp/SoundGroup.cs
new file mode 100644
index 0000000..b7ec876
--- /dev/null
+++ b/Client/Assembly-CSharp/SoundGroup.cs
@@ -0,0 +1,13 @@
+using System;
+using UnityEngine;
+
+[CreateAssetMenu]
+public class SoundGroup : ScriptableObject
+{
+ public AudioClip[] Clips;
+
+ public AudioClip Random()
+ {
+ return this.Clips.Random<AudioClip>();
+ }
+}
diff --git a/Client/Assembly-CSharp/SoundManager.cs b/Client/Assembly-CSharp/SoundManager.cs
new file mode 100644
index 0000000..4d03573
--- /dev/null
+++ b/Client/Assembly-CSharp/SoundManager.cs
@@ -0,0 +1,239 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.Audio;
+
+public class SoundManager : MonoBehaviour
+{
+ public static SoundManager Instance
+ {
+ get
+ {
+ if (!SoundManager._Instance)
+ {
+ SoundManager._Instance = (UnityEngine.Object.FindObjectOfType<SoundManager>() ?? new GameObject("SoundManager").AddComponent<SoundManager>());
+ }
+ return SoundManager._Instance;
+ }
+ }
+
+ private static SoundManager _Instance;
+
+ public AudioMixerGroup musicMixer;
+
+ public AudioMixerGroup sfxMixer;
+
+ public static float MusicVolume = 1f;
+
+ public static float SfxVolume = 1f;
+
+ private Dictionary<AudioClip, AudioSource> allSources = new Dictionary<AudioClip, AudioSource>();
+
+ private List<ISoundPlayer> soundPlayers = new List<ISoundPlayer>();
+
+ public void Start()
+ {
+ if (SoundManager._Instance && SoundManager._Instance != this)
+ {
+ UnityEngine.Object.Destroy(base.gameObject);
+ return;
+ }
+ SoundManager._Instance = this;
+ this.UpdateVolume();
+ UnityEngine.Object.DontDestroyOnLoad(base.gameObject);
+ }
+
+ public void Update()
+ {
+ for (int i = 0; i < this.soundPlayers.Count; i++)
+ {
+ this.soundPlayers[i].Update(Time.deltaTime);
+ }
+ }
+
+ private void UpdateVolume()
+ {
+ this.ChangeSfxVolume(SaveManager.SfxVolume);
+ this.ChangeMusicVolume(SaveManager.MusicVolume);
+ }
+
+ public void ChangeSfxVolume(float volume)
+ {
+ if (volume <= 0f)
+ {
+ SoundManager.SfxVolume = -80f;
+ }
+ else
+ {
+ SoundManager.SfxVolume = Mathf.Log10(volume) * 20f;
+ }
+ this.musicMixer.audioMixer.SetFloat("SfxVolume", SoundManager.SfxVolume);
+ }
+
+ public void ChangeMusicVolume(float volume)
+ {
+ if (volume <= 0f)
+ {
+ SoundManager.MusicVolume = -80f;
+ }
+ else
+ {
+ SoundManager.MusicVolume = Mathf.Log10(volume) * 20f;
+ }
+ this.musicMixer.audioMixer.SetFloat("MusicVolume", SoundManager.MusicVolume);
+ }
+
+ public void StopSound(AudioClip clip)
+ {
+ AudioSource audioSource;
+ if (this.allSources.TryGetValue(clip, out audioSource))
+ {
+ this.allSources.Remove(clip);
+ audioSource.Stop();
+ UnityEngine.Object.Destroy(audioSource);
+ }
+ for (int i = 0; i < this.soundPlayers.Count; i++)
+ {
+ ISoundPlayer soundPlayer = this.soundPlayers[i];
+ if (soundPlayer.Player.clip == clip)
+ {
+ UnityEngine.Object.Destroy(soundPlayer.Player);
+ this.soundPlayers.RemoveAt(i);
+ return;
+ }
+ }
+ }
+
+ public void StopAllSound()
+ {
+ for (int i = 0; i < this.soundPlayers.Count; i++)
+ {
+ UnityEngine.Object.Destroy(this.soundPlayers[i].Player);
+ }
+ this.soundPlayers.Clear();
+ foreach (KeyValuePair<AudioClip, AudioSource> keyValuePair in this.allSources)
+ {
+ AudioSource value = keyValuePair.Value;
+ value.volume = 0f;
+ value.Stop();
+ UnityEngine.Object.Destroy(keyValuePair.Value);
+ }
+ this.allSources.Clear();
+ }
+
+ public void PlayDynamicSound(string name, AudioClip clip, bool loop, DynamicSound.GetDynamicsFunction volumeFunc, bool playAsSfx = false)
+ {
+ DynamicSound dynamicSound = null;
+ for (int i = 0; i < this.soundPlayers.Count; i++)
+ {
+ ISoundPlayer soundPlayer = this.soundPlayers[i];
+ if (soundPlayer.Name == name && soundPlayer is DynamicSound)
+ {
+ dynamicSound = (DynamicSound)soundPlayer;
+ break;
+ }
+ }
+ if (dynamicSound == null)
+ {
+ dynamicSound = new DynamicSound();
+ dynamicSound.Name = name;
+ dynamicSound.Player = base.gameObject.AddComponent<AudioSource>();
+ dynamicSound.Player.outputAudioMixerGroup = ((loop && !playAsSfx) ? this.musicMixer : this.sfxMixer);
+ dynamicSound.Player.playOnAwake = false;
+ this.soundPlayers.Add(dynamicSound);
+ }
+ dynamicSound.Player.loop = loop;
+ dynamicSound.SetTarget(clip, volumeFunc);
+ }
+
+ public void CrossFadeSound(string name, AudioClip clip, float maxVolume, float duration = 1.5f)
+ {
+ CrossFader crossFader = null;
+ for (int i = 0; i < this.soundPlayers.Count; i++)
+ {
+ ISoundPlayer soundPlayer = this.soundPlayers[i];
+ if (soundPlayer.Name == name && soundPlayer is CrossFader)
+ {
+ crossFader = (CrossFader)soundPlayer;
+ break;
+ }
+ }
+ if (crossFader == null)
+ {
+ crossFader = new CrossFader();
+ crossFader.Name = name;
+ crossFader.MaxVolume = maxVolume;
+ crossFader.Player = base.gameObject.AddComponent<AudioSource>();
+ crossFader.Player.outputAudioMixerGroup = this.musicMixer;
+ crossFader.Player.playOnAwake = false;
+ crossFader.Player.loop = true;
+ this.soundPlayers.Add(crossFader);
+ }
+ crossFader.SetTarget(clip);
+ }
+
+ public AudioSource PlaySoundImmediate(AudioClip clip, bool loop, float volume = 1f, float pitch = 1f)
+ {
+ if (clip == null)
+ {
+ Debug.LogWarning("Missing audio clip");
+ return null;
+ }
+ AudioSource audioSource;
+ if (this.allSources.TryGetValue(clip, out audioSource))
+ {
+ audioSource.pitch = pitch;
+ audioSource.loop = loop;
+ audioSource.Play();
+ }
+ else
+ {
+ audioSource = base.gameObject.AddComponent<AudioSource>();
+ audioSource.outputAudioMixerGroup = (loop ? this.musicMixer : this.sfxMixer);
+ audioSource.playOnAwake = false;
+ audioSource.volume = volume;
+ audioSource.pitch = pitch;
+ audioSource.loop = loop;
+ audioSource.clip = clip;
+ audioSource.Play();
+ this.allSources.Add(clip, audioSource);
+ }
+ return audioSource;
+ }
+
+ public bool SoundIsPlaying(AudioClip clip)
+ {
+ AudioSource audioSource;
+ return this.allSources.TryGetValue(clip, out audioSource) && !audioSource.isPlaying;
+ }
+
+ public AudioSource PlaySound(AudioClip clip, bool loop, float volume = 1f)
+ {
+ if (clip == null)
+ {
+ Debug.LogWarning("Missing audio clip");
+ return null;
+ }
+ AudioSource audioSource;
+ if (this.allSources.TryGetValue(clip, out audioSource))
+ {
+ if (!audioSource.isPlaying)
+ {
+ audioSource.loop = loop;
+ audioSource.Play();
+ }
+ }
+ else
+ {
+ audioSource = base.gameObject.AddComponent<AudioSource>();
+ audioSource.outputAudioMixerGroup = (loop ? this.musicMixer : this.sfxMixer);
+ audioSource.playOnAwake = false;
+ audioSource.volume = volume;
+ audioSource.loop = loop;
+ audioSource.clip = clip;
+ audioSource.Play();
+ this.allSources.Add(clip, audioSource);
+ }
+ return audioSource;
+ }
+}
diff --git a/Client/Assembly-CSharp/SoundStarter.cs b/Client/Assembly-CSharp/SoundStarter.cs
new file mode 100644
index 0000000..0a1258e
--- /dev/null
+++ b/Client/Assembly-CSharp/SoundStarter.cs
@@ -0,0 +1,23 @@
+using System;
+using UnityEngine;
+
+public class SoundStarter : MonoBehaviour
+{
+ public string Name;
+
+ public AudioClip SoundToPlay;
+
+ public bool StopAll;
+
+ [Range(0f, 1f)]
+ public float Volume = 1f;
+
+ public void Awake()
+ {
+ if (this.StopAll)
+ {
+ SoundManager.Instance.StopAllSound();
+ }
+ SoundManager.Instance.CrossFadeSound(this.Name, this.SoundToPlay, this.Volume, 1.5f);
+ }
+}
diff --git a/Client/Assembly-CSharp/SpinAnimator.cs b/Client/Assembly-CSharp/SpinAnimator.cs
new file mode 100644
index 0000000..e3762f2
--- /dev/null
+++ b/Client/Assembly-CSharp/SpinAnimator.cs
@@ -0,0 +1,72 @@
+using System;
+using System.Collections;
+using UnityEngine;
+
+public class SpinAnimator : MonoBehaviour
+{
+ public float Speed = 60f;
+
+ private SpinAnimator.States curState;
+
+ private enum States
+ {
+ Visible,
+ Invisible,
+ Spinning,
+ Pulsing
+ }
+
+ private void Update()
+ {
+ if (this.curState == SpinAnimator.States.Spinning)
+ {
+ base.transform.Rotate(0f, 0f, this.Speed * Time.deltaTime);
+ }
+ }
+
+ public void Appear()
+ {
+ if (this.curState != SpinAnimator.States.Invisible)
+ {
+ return;
+ }
+ this.curState = SpinAnimator.States.Visible;
+ base.gameObject.SetActive(true);
+ base.StopAllCoroutines();
+ base.StartCoroutine(Effects.ScaleIn(base.transform, 0f, 1f, 0.125f));
+ }
+
+ public void Disappear()
+ {
+ if (this.curState == SpinAnimator.States.Invisible)
+ {
+ return;
+ }
+ this.curState = SpinAnimator.States.Invisible;
+ base.StopAllCoroutines();
+ base.StartCoroutine(this.CoDisappear());
+ }
+
+ private IEnumerator CoDisappear()
+ {
+ yield return Effects.ScaleIn(base.transform, 1f, 0f, 0.125f);
+ base.gameObject.SetActive(false);
+ yield break;
+ }
+
+ public void StartPulse()
+ {
+ if (this.curState == SpinAnimator.States.Pulsing)
+ {
+ return;
+ }
+ this.curState = SpinAnimator.States.Pulsing;
+ SpriteRenderer component = base.GetComponent<SpriteRenderer>();
+ base.StartCoroutine(Effects.CycleColors(component, Color.white, Color.green, 1f, float.MaxValue));
+ }
+
+ internal void Play()
+ {
+ this.curState = SpinAnimator.States.Spinning;
+ }
+}
diff --git a/Client/Assembly-CSharp/SpriteParticle.cs b/Client/Assembly-CSharp/SpriteParticle.cs
new file mode 100644
index 0000000..8661403
--- /dev/null
+++ b/Client/Assembly-CSharp/SpriteParticle.cs
@@ -0,0 +1,128 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+[RequireComponent(typeof(MeshFilter))]
+[RequireComponent(typeof(MeshRenderer))]
+public class SpriteParticle : MonoBehaviour
+{
+ private const float FrameRate = 24f;
+
+ public Sprite[] Sprites;
+
+ public ParticleInfo[] Particles;
+
+ public ushort[][] TriangleCache;
+
+ private Vector3[] verts;
+
+ private Vector2[] uvs;
+
+ private List<int> tris = new List<int>();
+
+ private Mesh mesh;
+
+ private int MaxVerts;
+
+ private Dictionary<int, Vector2[]> VertCache = new Dictionary<int, Vector2[]>();
+
+ private Dictionary<int, Vector2[]> UvCache = new Dictionary<int, Vector2[]>();
+
+ public void OnDrawGizmos()
+ {
+ if (this.Particles == null || this.Sprites == null)
+ {
+ return;
+ }
+ if (this.Sprites.Length == 0)
+ {
+ return;
+ }
+ Sprite sprite = this.Sprites[0];
+ for (int i = 0; i < this.Particles.Length; i++)
+ {
+ ParticleInfo particleInfo = this.Particles[i];
+ Gizmos.DrawCube(particleInfo.Position + base.transform.position, new Vector3(sprite.bounds.size.x * particleInfo.Scale, sprite.bounds.size.y * particleInfo.Scale, sprite.bounds.size.x * particleInfo.Scale));
+ }
+ }
+
+ public void Start()
+ {
+ MeshFilter component = base.GetComponent<MeshFilter>();
+ this.mesh = new Mesh();
+ this.mesh.MarkDynamic();
+ component.mesh = this.mesh;
+ this.TriangleCache = new ushort[this.Sprites.Length][];
+ for (int i = 0; i < this.Sprites.Length; i++)
+ {
+ Sprite sprite = this.Sprites[i];
+ Vector2[] vertices = sprite.vertices;
+ this.TriangleCache[i] = sprite.triangles;
+ this.VertCache[i] = vertices;
+ this.UvCache[i] = sprite.uv;
+ if (this.MaxVerts < vertices.Length)
+ {
+ this.MaxVerts = vertices.Length;
+ }
+ }
+ this.verts = new Vector3[this.Particles.Length * this.MaxVerts];
+ this.uvs = new Vector2[this.verts.Length];
+ for (int j = 0; j < this.Particles.Length; j++)
+ {
+ int num = j * this.MaxVerts;
+ int num2 = (int)this.Particles[j].Timer;
+ Sprite sprite2 = this.Sprites[num2];
+ Vector2[] vertices2 = sprite2.vertices;
+ Vector2[] uv = sprite2.uv;
+ for (int k = 0; k < sprite2.vertices.Length; k++)
+ {
+ int num3 = num + k;
+ this.verts[num3].x = vertices2[k].x * this.Particles[j].Scale + this.Particles[j].Position.x;
+ this.verts[num3].y = vertices2[k].y * this.Particles[j].Scale + this.Particles[j].Position.y;
+ this.uvs[num3] = uv[k];
+ }
+ ushort[] triangles = sprite2.triangles;
+ for (int l = 0; l < triangles.Length; l++)
+ {
+ this.tris.Add((int)triangles[l]);
+ }
+ }
+ this.mesh.vertices = this.verts;
+ this.mesh.uv = this.uvs;
+ this.mesh.SetTriangles(this.tris, 0);
+ }
+
+ public void Update()
+ {
+ float num = Time.deltaTime * 24f;
+ this.tris.Clear();
+ for (int i = 0; i < this.Particles.Length; i++)
+ {
+ float num2 = this.Particles[i].Timer + num;
+ if (num2 >= (float)this.Sprites.Length)
+ {
+ num2 %= 24f;
+ }
+ this.Particles[i].Timer = num2;
+ int num3 = i * this.MaxVerts;
+ int num4 = (int)this.Particles[i].Timer;
+ Vector2[] array = this.VertCache[num4];
+ Vector2[] array2 = this.UvCache[num4];
+ for (int j = 0; j < array.Length; j++)
+ {
+ int num5 = num3 + j;
+ this.verts[num5].x = array[j].x * this.Particles[i].Scale + this.Particles[i].Position.x;
+ this.verts[num5].y = array[j].y * this.Particles[i].Scale + this.Particles[i].Position.y;
+ this.uvs[num5] = array2[j];
+ }
+ ushort[] array3 = this.TriangleCache[num4];
+ for (int k = 0; k < array3.Length; k++)
+ {
+ this.tris.Add((int)array3[k] + num3);
+ }
+ }
+ this.mesh.vertices = this.verts;
+ this.mesh.uv = this.uvs;
+ this.mesh.SetTriangles(this.tris, 0);
+ }
+}
diff --git a/Client/Assembly-CSharp/StarGen.cs b/Client/Assembly-CSharp/StarGen.cs
new file mode 100644
index 0000000..2ecd529
--- /dev/null
+++ b/Client/Assembly-CSharp/StarGen.cs
@@ -0,0 +1,170 @@
+using System;
+using UnityEngine;
+
+[RequireComponent(typeof(MeshFilter))]
+[RequireComponent(typeof(MeshRenderer))]
+public class StarGen : MonoBehaviour
+{
+ private const float MaxStarRadius = 0.05f;
+
+ public int NumStars = 500;
+
+ public float Length = 25f;
+
+ public float Width = 25f;
+
+ public Vector2 Direction = new Vector2(1f, 0f);
+
+ private Vector2 NormDir = new Vector2(1f, 0f);
+
+ private Vector2 Tangent = new Vector2(0f, 1f);
+
+ private float tanLen;
+
+ public FloatRange Rates = new FloatRange(0.25f, 1f);
+
+ [HideInInspector]
+ private StarGen.Stars[] stars;
+
+ [HideInInspector]
+ private Vector3[] verts;
+
+ [HideInInspector]
+ private Mesh mesh;
+
+ [Serializable]
+ private struct Stars
+ {
+ public float Size;
+
+ public float Rate;
+
+ public float PositionX;
+
+ public float PositionY;
+ }
+
+ public void Start()
+ {
+ this.stars = new StarGen.Stars[this.NumStars];
+ this.verts = new Vector3[this.NumStars * 4];
+ Vector2[] array = new Vector2[this.NumStars * 4];
+ int[] array2 = new int[this.NumStars * 6];
+ this.SetDirection(this.Direction);
+ MeshFilter component = base.GetComponent<MeshFilter>();
+ this.mesh = new Mesh();
+ this.mesh.MarkDynamic();
+ component.mesh = this.mesh;
+ Vector3 vector = default(Vector3);
+ Vector2 vector2 = default(Vector2);
+ for (int i = 0; i < this.stars.Length; i++)
+ {
+ StarGen.Stars stars = this.stars[i];
+ float num = FloatRange.Next(-1f, 1f) * this.Length;
+ float num2 = FloatRange.Next(-1f, 1f) * this.Width;
+ float num3 = stars.PositionX = num * this.NormDir.x + num2 * this.Tangent.x;
+ float num4 = stars.PositionY = num * this.NormDir.y + num2 * this.Tangent.y;
+ float num5 = FloatRange.Next(0.01f, 0.05f);
+ stars.Size = num5;
+ stars.Rate = this.Rates.Next();
+ this.stars[i] = stars;
+ int num6 = i * 4;
+ vector.x = num3 - num5;
+ vector.y = num4 + num5;
+ this.verts[num6] = vector;
+ vector.y = num4 - num5;
+ this.verts[num6 + 1] = vector;
+ vector.x = num3 + num5;
+ this.verts[num6 + 2] = vector;
+ vector.y = num4 + num5;
+ this.verts[num6 + 3] = vector;
+ vector2.x = -1f;
+ vector2.y = 1f;
+ array[num6] = vector2;
+ vector2.y = -1f;
+ array[num6 + 1] = vector2;
+ vector2.x = 1f;
+ array[num6 + 2] = vector2;
+ vector2.y = 1f;
+ array[num6 + 3] = vector2;
+ int num7 = i * 6;
+ array2[num7] = num6;
+ array2[num7 + 1] = num6 + 1;
+ array2[num7 + 2] = num6 + 2;
+ array2[num7 + 3] = num6 + 2;
+ array2[num7 + 4] = num6;
+ array2[num7 + 5] = num6 + 3;
+ }
+ this.mesh.vertices = this.verts;
+ this.mesh.uv = array;
+ this.mesh.SetIndices(array2, MeshTopology.Triangles, 0);
+ }
+
+ private void FixedUpdate()
+ {
+ float num = -0.99f * this.Length;
+ Vector2 vector = this.Direction * Time.fixedDeltaTime;
+ for (int i = 0; i < this.stars.Length; i++)
+ {
+ StarGen.Stars stars = this.stars[i];
+ float size = stars.Size;
+ float num2 = stars.PositionX;
+ float num3 = stars.PositionY;
+ float num4 = stars.Rate * (size / 0.05f);
+ num2 += num4 * vector.x;
+ num3 += num4 * vector.y;
+ if (this.OrthoDistance(num2, num3) > this.Length)
+ {
+ float num5 = FloatRange.Next(-1f, 1f) * this.Width;
+ num2 = num * this.NormDir.x + num5 * this.Tangent.x;
+ num3 = num * this.NormDir.y + num5 * this.Tangent.y;
+ this.stars[i].Rate = this.Rates.Next();
+ }
+ stars.PositionX = num2;
+ stars.PositionY = num3;
+ this.stars[i] = stars;
+ int num6 = i * 4;
+ float x = num2 - size;
+ float x2 = num2 + size;
+ float y = num3 + size;
+ float y2 = num3 - size;
+ this.verts[num6].x = x;
+ this.verts[num6].y = y;
+ this.verts[num6 + 1].x = x;
+ this.verts[num6 + 1].y = y2;
+ this.verts[num6 + 2].x = x2;
+ this.verts[num6 + 2].y = y2;
+ this.verts[num6 + 3].x = x2;
+ this.verts[num6 + 3].y = y;
+ }
+ this.mesh.vertices = this.verts;
+ }
+
+ public void SetDirection(Vector2 dir)
+ {
+ this.Direction = dir;
+ this.NormDir = this.Direction.normalized;
+ this.Tangent = new Vector2(-this.NormDir.y, this.NormDir.x);
+ this.tanLen = Mathf.Sqrt(this.Tangent.y * this.Tangent.y + this.Tangent.x * this.Tangent.x);
+ }
+
+ public void RegenPositions()
+ {
+ if (this.stars == null)
+ {
+ return;
+ }
+ for (int i = 0; i < this.stars.Length; i++)
+ {
+ float num = FloatRange.Next(-1f, 1f) * this.Length;
+ float num2 = FloatRange.Next(-1f, 1f) * this.Width;
+ this.stars[i].PositionX = num * this.NormDir.x + num2 * this.Tangent.x;
+ this.stars[i].PositionY = num * this.NormDir.y + num2 * this.Tangent.y;
+ }
+ }
+
+ private float OrthoDistance(float pointx, float pointy)
+ {
+ return (this.Tangent.y * pointx - this.Tangent.x * pointy) / this.tanLen;
+ }
+}
diff --git a/Client/Assembly-CSharp/StatsManager.cs b/Client/Assembly-CSharp/StatsManager.cs
new file mode 100644
index 0000000..1b26ce2
--- /dev/null
+++ b/Client/Assembly-CSharp/StatsManager.cs
@@ -0,0 +1,439 @@
+using System;
+using System.IO;
+using UnityEngine;
+
+public class StatsManager
+{
+ public uint BodiesReported
+ {
+ get
+ {
+ this.LoadStats();
+ return this.bodiesReported;
+ }
+ set
+ {
+ this.LoadStats();
+ this.bodiesReported = value;
+ this.SaveStats();
+ }
+ }
+
+ public uint EmergenciesCalled
+ {
+ get
+ {
+ this.LoadStats();
+ return this.emergenciesCalls;
+ }
+ set
+ {
+ this.LoadStats();
+ this.emergenciesCalls = value;
+ this.SaveStats();
+ }
+ }
+
+ public uint TasksCompleted
+ {
+ get
+ {
+ this.LoadStats();
+ return this.tasksCompleted;
+ }
+ set
+ {
+ this.LoadStats();
+ this.tasksCompleted = value;
+ this.SaveStats();
+ }
+ }
+
+ public uint CompletedAllTasks
+ {
+ get
+ {
+ this.LoadStats();
+ return this.completedAllTasks;
+ }
+ set
+ {
+ this.LoadStats();
+ this.completedAllTasks = value;
+ this.SaveStats();
+ }
+ }
+
+ public uint SabsFixed
+ {
+ get
+ {
+ this.LoadStats();
+ return this.sabsFixed;
+ }
+ set
+ {
+ this.LoadStats();
+ this.sabsFixed = value;
+ this.SaveStats();
+ }
+ }
+
+ public uint ImpostorKills
+ {
+ get
+ {
+ this.LoadStats();
+ return this.impostorKills;
+ }
+ set
+ {
+ this.LoadStats();
+ this.impostorKills = value;
+ this.SaveStats();
+ }
+ }
+
+ public uint TimesMurdered
+ {
+ get
+ {
+ this.LoadStats();
+ return this.timesMurdered;
+ }
+ set
+ {
+ this.LoadStats();
+ this.timesMurdered = value;
+ this.SaveStats();
+ }
+ }
+
+ public uint TimesEjected
+ {
+ get
+ {
+ this.LoadStats();
+ return this.timesEjected;
+ }
+ set
+ {
+ this.LoadStats();
+ this.timesEjected = value;
+ this.SaveStats();
+ }
+ }
+
+ public uint CrewmateStreak
+ {
+ get
+ {
+ this.LoadStats();
+ return this.crewmateStreak;
+ }
+ set
+ {
+ this.LoadStats();
+ this.crewmateStreak = value;
+ this.SaveStats();
+ }
+ }
+
+ public uint TimesImpostor
+ {
+ get
+ {
+ this.LoadStats();
+ return this.timesImpostor;
+ }
+ set
+ {
+ this.LoadStats();
+ this.timesImpostor = value;
+ this.SaveStats();
+ }
+ }
+
+ public uint TimesCrewmate
+ {
+ get
+ {
+ this.LoadStats();
+ return this.timesCrewmate;
+ }
+ set
+ {
+ this.LoadStats();
+ this.timesCrewmate = value;
+ this.SaveStats();
+ }
+ }
+
+ public uint GamesStarted
+ {
+ get
+ {
+ this.LoadStats();
+ return this.gamesStarted;
+ }
+ set
+ {
+ this.LoadStats();
+ this.gamesStarted = value;
+ this.SaveStats();
+ }
+ }
+
+ public uint GamesFinished
+ {
+ get
+ {
+ this.LoadStats();
+ return this.gamesFinished;
+ }
+ set
+ {
+ this.LoadStats();
+ this.gamesFinished = value;
+ this.SaveStats();
+ }
+ }
+
+ public float BanPoints
+ {
+ get
+ {
+ this.LoadStats();
+ return this.banPoints;
+ }
+ set
+ {
+ this.LoadStats();
+ this.banPoints = Mathf.Max(0f, value);
+ this.SaveStats();
+ }
+ }
+
+ public DateTime LastGameStarted
+ {
+ get
+ {
+ this.LoadStats();
+ return new DateTime(this.lastGameStarted);
+ }
+ set
+ {
+ this.LoadStats();
+ this.lastGameStarted = value.Ticks;
+ this.SaveStats();
+ }
+ }
+
+ public float BanMinutes
+ {
+ get
+ {
+ return Mathf.Max(this.BanPoints - 2f, 0f) * 5f;
+ }
+ }
+
+ public bool AmBanned
+ {
+ get
+ {
+ return this.BanMinutesLeft > 0;
+ }
+ }
+
+ public int BanMinutesLeft
+ {
+ get
+ {
+ TimeSpan timeSpan = DateTime.UtcNow - this.LastGameStarted;
+ if (timeSpan.TotalDays > 1.0)
+ {
+ return 0;
+ }
+ return Mathf.CeilToInt(this.BanMinutes - (float)timeSpan.TotalMinutes);
+ }
+ }
+
+ public static StatsManager Instance = new StatsManager();
+
+ private const byte StatsVersion = 3;
+
+ private bool loadedStats;
+
+ private uint bodiesReported;
+
+ private uint emergenciesCalls;
+
+ private uint tasksCompleted;
+
+ private uint completedAllTasks;
+
+ private uint sabsFixed;
+
+ private uint impostorKills;
+
+ private uint timesMurdered;
+
+ private uint timesEjected;
+
+ private uint crewmateStreak;
+
+ private uint timesImpostor;
+
+ private uint timesCrewmate;
+
+ private uint gamesStarted;
+
+ private uint gamesFinished;
+
+ private float banPoints;
+
+ private long lastGameStarted;
+
+ private const int PointsUntilBanStarts = 2;
+
+ private const int MinutesPerBanPoint = 5;
+
+ private uint[] WinReasons = new uint[7];
+
+ private uint[] DrawReasons = new uint[7];
+
+ private uint[] LoseReasons = new uint[7];
+
+ public void AddDrawReason(GameOverReason reason)
+ {
+ this.LoadStats();
+ this.DrawReasons[(int)reason] += 1U;
+ this.SaveStats();
+ }
+
+ public void AddWinReason(GameOverReason reason)
+ {
+ this.LoadStats();
+ this.WinReasons[(int)reason] += 1U;
+ this.SaveStats();
+ }
+
+ public uint GetWinReason(GameOverReason reason)
+ {
+ this.LoadStats();
+ return this.WinReasons[(int)reason];
+ }
+
+ public void AddLoseReason(GameOverReason reason)
+ {
+ this.LoadStats();
+ this.LoseReasons[(int)reason] += 1U;
+ this.SaveStats();
+ }
+
+ public uint GetLoseReason(GameOverReason reason)
+ {
+ this.LoadStats();
+ return this.LoseReasons[(int)reason];
+ }
+
+ protected virtual void LoadStats()
+ {
+ if (this.loadedStats)
+ {
+ return;
+ }
+ this.loadedStats = true;
+ string path = Path.Combine(Application.persistentDataPath, "playerStats2");
+ if (File.Exists(path))
+ {
+ try
+ {
+ using (BinaryReader binaryReader = new BinaryReader(File.OpenRead(path)))
+ {
+ byte b = binaryReader.ReadByte();
+ this.bodiesReported = binaryReader.ReadUInt32();
+ this.emergenciesCalls = binaryReader.ReadUInt32();
+ this.tasksCompleted = binaryReader.ReadUInt32();
+ this.completedAllTasks = binaryReader.ReadUInt32();
+ this.sabsFixed = binaryReader.ReadUInt32();
+ this.impostorKills = binaryReader.ReadUInt32();
+ this.timesMurdered = binaryReader.ReadUInt32();
+ this.timesEjected = binaryReader.ReadUInt32();
+ this.crewmateStreak = binaryReader.ReadUInt32();
+ this.timesImpostor = binaryReader.ReadUInt32();
+ this.timesCrewmate = binaryReader.ReadUInt32();
+ this.gamesStarted = binaryReader.ReadUInt32();
+ this.gamesFinished = binaryReader.ReadUInt32();
+ for (int i = 0; i < this.WinReasons.Length; i++)
+ {
+ this.WinReasons[i] = binaryReader.ReadUInt32();
+ }
+ for (int j = 0; j < this.LoseReasons.Length; j++)
+ {
+ this.LoseReasons[j] = binaryReader.ReadUInt32();
+ }
+ if (b > 1)
+ {
+ for (int k = 0; k < this.DrawReasons.Length; k++)
+ {
+ this.DrawReasons[k] = binaryReader.ReadUInt32();
+ }
+ }
+ if (b > 2)
+ {
+ this.banPoints = binaryReader.ReadSingle();
+ this.lastGameStarted = binaryReader.ReadInt64();
+ }
+ }
+ }
+ catch
+ {
+ Debug.LogError("Deleting corrupted stats file");
+ File.Delete(path);
+ }
+ }
+ }
+
+ protected virtual void SaveStats()
+ {
+ try
+ {
+ using (BinaryWriter binaryWriter = new BinaryWriter(File.OpenWrite(Path.Combine(Application.persistentDataPath, "playerStats2"))))
+ {
+ binaryWriter.Write(3);
+ binaryWriter.Write(this.bodiesReported);
+ binaryWriter.Write(this.emergenciesCalls);
+ binaryWriter.Write(this.tasksCompleted);
+ binaryWriter.Write(this.completedAllTasks);
+ binaryWriter.Write(this.sabsFixed);
+ binaryWriter.Write(this.impostorKills);
+ binaryWriter.Write(this.timesMurdered);
+ binaryWriter.Write(this.timesEjected);
+ binaryWriter.Write(this.crewmateStreak);
+ binaryWriter.Write(this.timesImpostor);
+ binaryWriter.Write(this.timesCrewmate);
+ binaryWriter.Write(this.gamesStarted);
+ binaryWriter.Write(this.gamesFinished);
+ for (int i = 0; i < this.WinReasons.Length; i++)
+ {
+ binaryWriter.Write(this.WinReasons[i]);
+ }
+ for (int j = 0; j < this.LoseReasons.Length; j++)
+ {
+ binaryWriter.Write(this.LoseReasons[j]);
+ }
+ for (int k = 0; k < this.DrawReasons.Length; k++)
+ {
+ binaryWriter.Write(this.DrawReasons[k]);
+ }
+ binaryWriter.Write(this.banPoints);
+ binaryWriter.Write(this.lastGameStarted);
+ }
+ }
+ catch (Exception ex)
+ {
+ Debug.Log("Failed to write out stats: " + ex.Message);
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/StatsPopup.cs b/Client/Assembly-CSharp/StatsPopup.cs
new file mode 100644
index 0000000..4ad2885
--- /dev/null
+++ b/Client/Assembly-CSharp/StatsPopup.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Text;
+using UnityEngine;
+
+public class StatsPopup : MonoBehaviour
+{
+ public TextRenderer StatsText;
+
+ private void OnEnable()
+ {
+ StringBuilder stringBuilder = new StringBuilder();
+ stringBuilder.AppendLine(string.Format("Bodies Reported:\t{0}", StatsManager.Instance.BodiesReported));
+ stringBuilder.AppendLine(string.Format("Emergencies Called:\t{0}", StatsManager.Instance.EmergenciesCalled));
+ stringBuilder.AppendLine(string.Format("Tasks Completed:\t{0}", StatsManager.Instance.TasksCompleted));
+ stringBuilder.AppendLine(string.Format("All Tasks Completed:\t{0}", StatsManager.Instance.CompletedAllTasks));
+ stringBuilder.AppendLine(string.Format("Sabotages Fixed:\t{0}", StatsManager.Instance.SabsFixed));
+ stringBuilder.AppendLine(string.Format("Impostor Kills: \t{0}", StatsManager.Instance.ImpostorKills));
+ stringBuilder.AppendLine(string.Format("Times Murdered:\t{0}", StatsManager.Instance.TimesMurdered));
+ stringBuilder.AppendLine(string.Format("Times Ejected: \t{0}", StatsManager.Instance.TimesEjected));
+ stringBuilder.AppendLine(string.Format("Crewmate Streak:\t{0}", StatsManager.Instance.CrewmateStreak));
+ stringBuilder.AppendLine(string.Format("Games Impostor:\t{0}", StatsManager.Instance.TimesImpostor));
+ stringBuilder.AppendLine(string.Format("Games Crewmate:\t{0}", StatsManager.Instance.TimesCrewmate));
+ stringBuilder.AppendLine(string.Format("Games Started: \t{0}", StatsManager.Instance.GamesStarted));
+ stringBuilder.AppendLine(string.Format("Games Finished:\t{0}", StatsManager.Instance.GamesFinished));
+ stringBuilder.AppendLine(string.Format("Impostor Vote Wins:\t{0}", StatsManager.Instance.GetWinReason(GameOverReason.ImpostorByVote)));
+ stringBuilder.AppendLine(string.Format("Impostor Kill Wins:\t{0}", StatsManager.Instance.GetWinReason(GameOverReason.ImpostorByKill)));
+ stringBuilder.AppendLine(string.Format("Impostor Sabotage Wins:\t{0}", StatsManager.Instance.GetWinReason(GameOverReason.ImpostorBySabotage)));
+ stringBuilder.AppendLine(string.Format("Crewmate Vote Wins:\t{0}", StatsManager.Instance.GetWinReason(GameOverReason.HumansByVote)));
+ stringBuilder.AppendLine(string.Format("Crewmate Task Wins:\t{0}", StatsManager.Instance.GetWinReason(GameOverReason.HumansByTask)));
+ this.StatsText.Text = stringBuilder.ToString();
+ }
+}
diff --git a/Client/Assembly-CSharp/SteamBehaviour.cs b/Client/Assembly-CSharp/SteamBehaviour.cs
new file mode 100644
index 0000000..515d641
--- /dev/null
+++ b/Client/Assembly-CSharp/SteamBehaviour.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Collections;
+using PowerTools;
+using UnityEngine;
+
+public class SteamBehaviour : MonoBehaviour
+{
+ public SpriteAnim anim;
+
+ public FloatRange PlayRate = new FloatRange(0.5f, 1f);
+
+ public void OnEnable()
+ {
+ base.StartCoroutine(this.Run());
+ }
+
+ private IEnumerator Run()
+ {
+ for (;;)
+ {
+ float time = this.PlayRate.Next();
+ while (time > 0f)
+ {
+ time -= Time.deltaTime;
+ yield return null;
+ }
+ this.anim.Play(null, 1f);
+ while (this.anim.IsPlaying(null))
+ {
+ yield return null;
+ }
+ }
+ yield break;
+ }
+}
diff --git a/Client/Assembly-CSharp/SteamManager.cs b/Client/Assembly-CSharp/SteamManager.cs
new file mode 100644
index 0000000..ce42f18
--- /dev/null
+++ b/Client/Assembly-CSharp/SteamManager.cs
@@ -0,0 +1,131 @@
+using System;
+using System.Text;
+using Steamworks;
+using UnityEngine;
+
+[DisallowMultipleComponent]
+public class SteamManager : MonoBehaviour
+{
+ private static SteamManager Instance
+ {
+ get
+ {
+ if (SteamManager.s_instance == null)
+ {
+ return new GameObject("SteamManager").AddComponent<SteamManager>();
+ }
+ return SteamManager.s_instance;
+ }
+ }
+
+ public static bool Initialized
+ {
+ get
+ {
+ return SteamManager.Instance.m_bInitialized;
+ }
+ }
+
+ private static SteamManager s_instance;
+
+ private static bool s_EverInitialized;
+
+ private bool m_bInitialized;
+
+ private SteamAPIWarningMessageHook_t m_SteamAPIWarningMessageHook;
+
+ private static void SteamAPIDebugTextHook(int nSeverity, StringBuilder pchDebugText)
+ {
+ Debug.LogWarning(pchDebugText);
+ }
+
+ private void Awake()
+ {
+ if (SteamManager.s_instance != null)
+ {
+ UnityEngine.Object.Destroy(base.gameObject);
+ return;
+ }
+ SteamManager.s_instance = this;
+ if (SteamManager.s_EverInitialized)
+ {
+ throw new Exception("Tried to Initialize the SteamAPI twice in one session!");
+ }
+ UnityEngine.Object.DontDestroyOnLoad(base.gameObject);
+ if (!Packsize.Test())
+ {
+ Debug.LogError("[Steamworks.NET] Packsize Test returned false, the wrong version of Steamworks.NET is being run in this platform.", this);
+ }
+ if (!DllCheck.Test())
+ {
+ Debug.LogError("[Steamworks.NET] DllCheck Test returned false, One or more of the Steamworks binaries seems to be the wrong version.", this);
+ }
+ try
+ {
+ if (SteamAPI.RestartAppIfNecessary(new AppId_t(945360U)))
+ {
+ Application.Quit();
+ return;
+ }
+ }
+ catch (DllNotFoundException arg)
+ {
+ Debug.LogError("[Steamworks.NET] Could not load [lib]steam_api.dll/so/dylib. It's likely not in the correct location. Refer to the README for more details.\n" + arg, this);
+ Application.Quit();
+ return;
+ }
+ this.m_bInitialized = SteamAPI.Init();
+ if (!this.m_bInitialized)
+ {
+ Debug.LogError("[Steamworks.NET] SteamAPI_Init() failed. Refer to Valve's documentation or the comment above this line for more information.", this);
+ return;
+ }
+ SteamManager.s_EverInitialized = true;
+ }
+
+ private void OnEnable()
+ {
+ if (SteamManager.s_instance == null)
+ {
+ SteamManager.s_instance = this;
+ }
+ if (!this.m_bInitialized)
+ {
+ return;
+ }
+ if (this.m_SteamAPIWarningMessageHook == null)
+ {
+ this.m_SteamAPIWarningMessageHook = new SteamAPIWarningMessageHook_t(SteamManager.SteamAPIDebugTextHook);
+ SteamClient.SetWarningMessageHook(this.m_SteamAPIWarningMessageHook);
+ }
+ }
+
+ private void OnDestroy()
+ {
+ if (SteamManager.s_instance != this)
+ {
+ return;
+ }
+ SteamManager.s_instance = null;
+ if (!this.m_bInitialized)
+ {
+ return;
+ }
+ SteamAPI.Shutdown();
+ }
+
+ [ContextMenu("Shutdown")]
+ private void DoShutdown()
+ {
+ SteamAPI.Shutdown();
+ }
+
+ private void Update()
+ {
+ if (!this.m_bInitialized)
+ {
+ return;
+ }
+ SteamAPI.RunCallbacks();
+ }
+}
diff --git a/Client/Assembly-CSharp/SteamPurchasingModule.cs b/Client/Assembly-CSharp/SteamPurchasingModule.cs
new file mode 100644
index 0000000..b3d80f1
--- /dev/null
+++ b/Client/Assembly-CSharp/SteamPurchasingModule.cs
@@ -0,0 +1,118 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using Steamworks;
+using UnityEngine;
+using UnityEngine.Purchasing;
+using UnityEngine.Purchasing.Extension;
+
+internal class SteamPurchasingModule : IPurchasingModule, IStore
+{
+ public const string Name = "Steam";
+
+ public Dictionary<string, uint> IdTranslator = new Dictionary<string, uint>(StringComparer.OrdinalIgnoreCase);
+
+ private IStoreCallback storeCallback;
+
+ private Callback<GameOverlayActivated_t> overlayCallback;
+
+ private bool steamOverlayOpen;
+
+ private StoreMenu parent;
+
+ public SteamPurchasingModule(StoreMenu parent)
+ {
+ this.parent = parent;
+ }
+
+ public void Configure(IPurchasingBinder binder)
+ {
+ binder.RegisterStore("Steam", this);
+ }
+
+ public void FinishTransaction(ProductDefinition product, string transactionId)
+ {
+ }
+
+ public void Initialize(IStoreCallback callback)
+ {
+ this.storeCallback = callback;
+ if (!SteamManager.Initialized || !SteamUtils.IsOverlayEnabled())
+ {
+ this.storeCallback.OnSetupFailed(InitializationFailureReason.PurchasingUnavailable);
+ }
+ this.overlayCallback = Callback<GameOverlayActivated_t>.Create(new Callback<GameOverlayActivated_t>.DispatchDelegate(this.HandleOverlayActivate));
+ }
+
+ private void HandleOverlayActivate(GameOverlayActivated_t param)
+ {
+ this.steamOverlayOpen = (param.m_bActive > 0);
+ }
+
+ public void Purchase(ProductDefinition product, string developerPayload)
+ {
+ if (!SteamUtils.IsOverlayEnabled())
+ {
+ this.storeCallback.OnPurchaseFailed(new PurchaseFailureDescription(product.storeSpecificId, PurchaseFailureReason.PurchasingUnavailable, "Steam overlay is disabled, but required for in-game purchasing."));
+ return;
+ }
+ uint value;
+ if (this.IdTranslator.TryGetValue(product.id, out value))
+ {
+ AppId_t appId_t = new AppId_t(value);
+ SteamFriends.ActivateGameOverlayToStore(appId_t, EOverlayToStoreFlag.k_EOverlayToStoreFlag_AddToCartAndShow);
+ this.parent.StartCoroutine(this.WaitForDlcPurchase(product, appId_t));
+ return;
+ }
+ this.storeCallback.OnPurchaseFailed(new PurchaseFailureDescription(product.storeSpecificId, PurchaseFailureReason.ProductUnavailable, "Couldn't find Product Id for " + product.id));
+ }
+
+ private IEnumerator WaitForDlcPurchase(ProductDefinition product, AppId_t appId)
+ {
+ while (!this.steamOverlayOpen)
+ {
+ SteamAPI.RunCallbacks();
+ yield return null;
+ }
+ while (this.steamOverlayOpen)
+ {
+ SteamAPI.RunCallbacks();
+ yield return null;
+ }
+ ulong num;
+ while (SteamApps.GetDlcDownloadProgress(appId, out num, out num))
+ {
+ yield return null;
+ }
+ if (SteamApps.BIsDlcInstalled(appId))
+ {
+ this.storeCallback.OnPurchaseSucceeded(product.id, "FakeReceipt", UnityEngine.Random.value.ToString());
+ }
+ else
+ {
+ this.storeCallback.OnPurchaseFailed(new PurchaseFailureDescription(product.id, PurchaseFailureReason.UserCancelled, "Steam overlay closed without purchase completing"));
+ }
+ yield break;
+ }
+
+ public void RetrieveProducts(ReadOnlyCollection<ProductDefinition> products)
+ {
+ if (!SteamManager.Initialized)
+ {
+ return;
+ }
+ List<ProductDescription> list = new List<ProductDescription>(products.Count);
+ for (int i = 0; i < products.Count; i++)
+ {
+ ProductDefinition productDefinition = products[i];
+ uint value;
+ if (this.IdTranslator.TryGetValue(productDefinition.id, out value))
+ {
+ bool flag = SteamApps.BIsDlcInstalled(new AppId_t(value));
+ list.Add(new ProductDescription(productDefinition.id, new ProductMetadata("$2.99", null, null, "USD", 1m), flag ? "Bought" : null, null));
+ }
+ }
+ this.storeCallback.OnProductsRetrieved(list);
+ }
+}
diff --git a/Client/Assembly-CSharp/StoreMenu.cs b/Client/Assembly-CSharp/StoreMenu.cs
new file mode 100644
index 0000000..a67399d
--- /dev/null
+++ b/Client/Assembly-CSharp/StoreMenu.cs
@@ -0,0 +1,409 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using PowerTools;
+using UnityEngine;
+using UnityEngine.Purchasing;
+using UnityEngine.Purchasing.Extension;
+
+public class StoreMenu : MonoBehaviour, IStoreListener
+{
+ public PurchaseStates PurchaseState { get; private set; }
+
+ public SpriteRenderer HatSlot;
+
+ public SpriteRenderer SkinSlot;
+
+ public SpriteAnim PetSlot;
+
+ public TextRenderer ItemName;
+
+ public SpriteRenderer PurchaseBackground;
+
+ public TextRenderer PriceText;
+
+ public PurchaseButton PurchasablePrefab;
+
+ public SpriteRenderer HortLinePrefab;
+
+ public TextRenderer LoadingText;
+
+ public TextRenderer RestorePurchasesButton;
+
+ public GameObject RestorePurchasesObj;
+
+ public SpriteRenderer BannerPrefab;
+
+ public Sprite HatBanner;
+
+ public Sprite SkinsBanner;
+
+ public Sprite HolidayBanner;
+
+ public Sprite PetsBanner;
+
+ public SpriteRenderer TopArrow;
+
+ public SpriteRenderer BottomArrow;
+
+ public const string BoughtAdsProductId = "bought_ads";
+
+ private IStoreController controller;
+
+ private IExtensionProvider extensions;
+
+ public Scroller Scroller;
+
+ public Vector2 StartPositionVertical;
+
+ public FloatRange XRange = new FloatRange(-1f, 1f);
+
+ public int NumPerRow = 4;
+
+ private PurchaseButton CurrentButton;
+
+ private List<GameObject> AllObjects = new List<GameObject>();
+
+ private const float NormalHeight = -0.45f;
+
+ private const float BoxHeight = -0.75f;
+
+ public void Start()
+ {
+ this.PetSlot.gameObject.SetActive(false);
+ SteamPurchasingModule steamPurchasingModule = new SteamPurchasingModule(this);
+ foreach (PetBehaviour petBehaviour in DestroyableSingleton<HatManager>.Instance.AllPets)
+ {
+ if (petBehaviour.SteamId != 0U)
+ {
+ steamPurchasingModule.IdTranslator.Add(petBehaviour.ProdId, petBehaviour.SteamId);
+ }
+ }
+ ConfigurationBuilder configurationBuilder = ConfigurationBuilder.Instance(steamPurchasingModule, Array.Empty<IPurchasingModule>());
+ foreach (PetBehaviour petBehaviour2 in DestroyableSingleton<HatManager>.Instance.AllPets)
+ {
+ if (!petBehaviour2.Free)
+ {
+ configurationBuilder.AddProduct(petBehaviour2.ProdId, ProductType.NonConsumable);
+ }
+ }
+ UnityPurchasing.Initialize(this, configurationBuilder);
+ this.PurchaseBackground.color = new Color(0.5f, 0.5f, 0.5f, 1f);
+ this.PriceText.Color = new Color(0.8f, 0.8f, 0.8f, 1f);
+ this.PriceText.Text = "";
+ }
+
+ public void Update()
+ {
+ this.TopArrow.enabled = !this.Scroller.AtTop;
+ this.BottomArrow.enabled = !this.Scroller.AtBottom;
+ }
+
+ public void RestorePurchases()
+ {
+ }
+
+ private void DestroySliderObjects()
+ {
+ for (int i = 0; i < this.AllObjects.Count; i++)
+ {
+ UnityEngine.Object.Destroy(this.AllObjects[i]);
+ }
+ this.AllObjects.Clear();
+ }
+
+ private void FinishRestoring()
+ {
+ this.ShowAllButtons();
+ this.RestorePurchasesButton.Text = "Purchases Restored";
+ }
+
+ public void SetProduct(PurchaseButton button)
+ {
+ if (this.PurchaseState == PurchaseStates.Started)
+ {
+ return;
+ }
+ this.CurrentButton = button;
+ if (this.CurrentButton.Product is HatBehaviour)
+ {
+ HatBehaviour hatBehaviour = (HatBehaviour)this.CurrentButton.Product;
+ this.HatSlot.gameObject.SetActive(true);
+ this.SkinSlot.gameObject.SetActive(false);
+ this.PetSlot.gameObject.SetActive(false);
+ PlayerControl.SetHatImage(hatBehaviour, this.HatSlot);
+ this.ItemName.Text = (string.IsNullOrWhiteSpace(hatBehaviour.StoreName) ? hatBehaviour.name : hatBehaviour.StoreName);
+ if (hatBehaviour.RelatedSkin)
+ {
+ TextRenderer itemName = this.ItemName;
+ itemName.Text += " (Includes skin!)";
+ this.SkinSlot.gameObject.SetActive(true);
+ PlayerControl.SetSkinImage(hatBehaviour.RelatedSkin, this.SkinSlot);
+ }
+ }
+ else if (this.CurrentButton.Product is SkinData)
+ {
+ SkinData skinData = (SkinData)this.CurrentButton.Product;
+ this.SkinSlot.gameObject.SetActive(true);
+ this.HatSlot.gameObject.SetActive(true);
+ this.PetSlot.gameObject.SetActive(false);
+ PlayerControl.SetHatImage(skinData.RelatedHat, this.HatSlot);
+ PlayerControl.SetSkinImage(skinData, this.SkinSlot);
+ this.ItemName.Text = (string.IsNullOrWhiteSpace(skinData.StoreName) ? skinData.name : skinData.StoreName);
+ }
+ else if (this.CurrentButton.Product is PetBehaviour)
+ {
+ PetBehaviour petBehaviour = (PetBehaviour)this.CurrentButton.Product;
+ this.SkinSlot.gameObject.SetActive(false);
+ this.HatSlot.gameObject.SetActive(false);
+ this.PetSlot.gameObject.SetActive(true);
+ SpriteRenderer component = this.PetSlot.GetComponent<SpriteRenderer>();
+ component.material = new Material(petBehaviour.rend.sharedMaterial);
+ PlayerControl.SetPlayerMaterialColors((int)SaveManager.BodyColor, component);
+ this.PetSlot.Play(petBehaviour.idleClip, 1f);
+ this.ItemName.Text = (string.IsNullOrWhiteSpace(petBehaviour.StoreName) ? petBehaviour.name : petBehaviour.StoreName);
+ }
+ else
+ {
+ this.HatSlot.gameObject.SetActive(false);
+ this.SkinSlot.gameObject.SetActive(false);
+ this.PetSlot.gameObject.SetActive(false);
+ this.ItemName.Text = "Remove All Ads";
+ }
+ if (button.Purchased)
+ {
+ this.PurchaseBackground.color = new Color(0.5f, 0.5f, 0.5f, 1f);
+ this.PriceText.Color = new Color(0.8f, 0.8f, 0.8f, 1f);
+ this.PriceText.Text = "Owned";
+ return;
+ }
+ this.PurchaseBackground.color = Color.white;
+ this.PriceText.Color = Color.white;
+ this.PriceText.Text = button.Price;
+ }
+
+ public void BuyProduct()
+ {
+ if (!this.CurrentButton || this.CurrentButton.Purchased || this.PurchaseState == PurchaseStates.Started)
+ {
+ return;
+ }
+ base.StartCoroutine(this.WaitForPurchaseAds(this.CurrentButton));
+ }
+
+ public IEnumerator WaitForPurchaseAds(PurchaseButton button)
+ {
+ this.PurchaseState = PurchaseStates.Started;
+ this.controller.InitiatePurchase(button.ProductId);
+ while (this.PurchaseState == PurchaseStates.Started)
+ {
+ yield return null;
+ }
+ if (this.PurchaseState == PurchaseStates.Success)
+ {
+ foreach (PurchaseButton purchaseButton in from p in this.AllObjects
+ select p.GetComponent<PurchaseButton>() into h
+ where h && h.ProductId == button.ProductId
+ select h)
+ {
+ purchaseButton.SetPurchased();
+ }
+ }
+ this.SetProduct(button);
+ yield break;
+ }
+
+ public void Close()
+ {
+ HatsTab hatsTab = UnityEngine.Object.FindObjectOfType<HatsTab>();
+ if (hatsTab)
+ {
+ hatsTab.OnDisable();
+ hatsTab.OnEnable();
+ }
+ base.gameObject.SetActive(false);
+ }
+
+ private void ShowAllButtons()
+ {
+ this.DestroySliderObjects();
+ string text = "";
+ try
+ {
+ text = "Couldn't fetch products";
+ foreach (Product product in this.controller.products.all)
+ {
+ if (product != null && product.hasReceipt)
+ {
+ try
+ {
+ SaveManager.SetPurchased(product.definition.id);
+ }
+ catch
+ {
+ }
+ }
+ }
+ Vector3 vector = this.StartPositionVertical;
+ UnityEngine.Object.Destroy(this.RestorePurchasesObj);
+ text = "Couldn't fetch products";
+ text = "Couldn't fetch pet data";
+ vector.y += -0.375f;
+ PetBehaviour[] array = (from h in DestroyableSingleton<HatManager>.Instance.AllPets
+ where !h.Free
+ select h into p
+ orderby p.StoreName
+ select p).ToArray<PetBehaviour>();
+ vector = this.InsertBanner(vector, this.PetsBanner);
+ Vector3 position = vector;
+ Product[] all;
+ Product[] allProducts = all;
+ IBuyable[] hats = array;
+ vector = this.InsertHatsFromList(position, allProducts, hats);
+ text = "Couldn't finalize menu";
+ this.Scroller.YBounds.max = Mathf.Max(0f, -vector.y - 2.5f);
+ this.LoadingText.gameObject.SetActive(false);
+ }
+ catch (Exception ex)
+ {
+ Debug.Log(string.Concat(new object[]
+ {
+ "Exception: ",
+ text,
+ ": ",
+ ex
+ }));
+ this.DestroySliderObjects();
+ this.LoadingText.gameObject.SetActive(true);
+ this.LoadingText.Text = "Loading Failed:\r\n" + text;
+ }
+ }
+
+ private Vector3 InsertHortLine(Vector3 position)
+ {
+ position.x = 1.2f;
+ SpriteRenderer spriteRenderer = UnityEngine.Object.Instantiate<SpriteRenderer>(this.HortLinePrefab, this.Scroller.Inner);
+ spriteRenderer.transform.localPosition = position;
+ spriteRenderer.gameObject.SetActive(true);
+ position.y += -0.33749998f;
+ return position;
+ }
+
+ private Vector3 InsertHatsFromList(Vector3 position, Product[] allProducts, IBuyable[] hats)
+ {
+ int num = 0;
+ for (int i = 0; i < hats.Length; i++)
+ {
+ IBuyable item = hats[i];
+ Product product = allProducts.FirstOrDefault((Product p) => item.ProdId == p.definition.id);
+ if (product != null && product.definition != null && product.availableToPurchase)
+ {
+ int num2 = num % this.NumPerRow;
+ position.x = this.StartPositionVertical.x + this.XRange.Lerp((float)num2 / ((float)this.NumPerRow - 1f));
+ if (num2 == 0 && num > 1)
+ {
+ position.y += -0.75f;
+ }
+ this.InsertProduct(position, product, item);
+ num++;
+ }
+ }
+ position.y += -0.75f;
+ return position;
+ }
+
+ private void InsertProduct(Vector3 position, Product product, IBuyable item)
+ {
+ PurchaseButton purchaseButton = UnityEngine.Object.Instantiate<PurchaseButton>(this.PurchasablePrefab, this.Scroller.Inner);
+ this.AllObjects.Add(purchaseButton.gameObject);
+ purchaseButton.transform.localPosition = position;
+ purchaseButton.Parent = this;
+ PurchaseButton purchaseButton2 = purchaseButton;
+ string id = product.definition.id;
+ ProductMetadata metadata = product.metadata;
+ string name;
+ if (metadata == null)
+ {
+ name = null;
+ }
+ else
+ {
+ string localizedTitle = metadata.localizedTitle;
+ name = ((localizedTitle != null) ? localizedTitle.Replace("(Among Us)", "") : null);
+ }
+ ProductMetadata metadata2 = product.metadata;
+ purchaseButton2.SetItem(item, id, name, (metadata2 != null) ? metadata2.localizedPriceString : null, product.hasReceipt || SaveManager.GetPurchase(product.definition.id));
+ }
+
+ private Vector3 InsertBanner(Vector3 position, Sprite s)
+ {
+ position.x = this.StartPositionVertical.x;
+ SpriteRenderer spriteRenderer = UnityEngine.Object.Instantiate<SpriteRenderer>(this.BannerPrefab, this.Scroller.Inner);
+ spriteRenderer.sprite = s;
+ spriteRenderer.transform.localPosition = position;
+ position.y += -spriteRenderer.sprite.bounds.size.y;
+ this.AllObjects.Add(spriteRenderer.gameObject);
+ return position;
+ }
+
+ public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
+ {
+ this.controller = controller;
+ this.extensions = extensions;
+ if (this.controller == null || this.controller.products == null)
+ {
+ this.LoadingText.Text = "Product controller\r\nfailed to load";
+ return;
+ }
+ this.ShowAllButtons();
+ }
+
+ public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs e)
+ {
+ this.PurchaseState = PurchaseStates.Success;
+ SaveManager.SetPurchased(e.purchasedProduct.definition.id);
+ return PurchaseProcessingResult.Complete;
+ }
+
+ public void OnInitializeFailed(InitializationFailureReason error)
+ {
+ this.RestorePurchasesObj.SetActive(false);
+ this.LoadingText.gameObject.SetActive(true);
+ if (error == InitializationFailureReason.NoProductsAvailable)
+ {
+ this.LoadingText.Text = "Coming Soon!";
+ return;
+ }
+ if (error == InitializationFailureReason.PurchasingUnavailable)
+ {
+ this.LoadingText.Text = "Loading Failed:\r\nSteam must be running and logged in to view products.";
+ return;
+ }
+ this.LoadingText.Text = "Loading Failed:\r\n" + error;
+ }
+
+ public void OnPurchaseFailed(Product i, PurchaseFailureReason error)
+ {
+ if (error == PurchaseFailureReason.ProductUnavailable)
+ {
+ this.DestroySliderObjects();
+ this.LoadingText.gameObject.SetActive(true);
+ this.LoadingText.Text = "Coming Soon!";
+ }
+ else if (error == PurchaseFailureReason.PurchasingUnavailable)
+ {
+ this.DestroySliderObjects();
+ this.LoadingText.gameObject.SetActive(true);
+ this.LoadingText.Text = "Steam overlay is required for in-game purchasing. You can still buy and install DLC in Steam.";
+ }
+ else
+ {
+ this.DestroySliderObjects();
+ this.LoadingText.gameObject.SetActive(true);
+ this.LoadingText.Text = "Loading Failed:\r\n" + error;
+ }
+ Debug.LogError("Failed: " + error);
+ this.PurchaseState = PurchaseStates.Fail;
+ }
+}
diff --git a/Client/Assembly-CSharp/StringExtensions.cs b/Client/Assembly-CSharp/StringExtensions.cs
new file mode 100644
index 0000000..dd37904
--- /dev/null
+++ b/Client/Assembly-CSharp/StringExtensions.cs
@@ -0,0 +1,32 @@
+using System;
+using UnityEngine;
+
+public static class StringExtensions
+{
+ private static char[] buffer = new char[256];
+
+ public static string Lerp(string a, string b, float t)
+ {
+ int num = Mathf.Max(a.Length, b.Length);
+ int num2 = (int)Mathf.Lerp(0f, (float)num, t);
+ for (int i = 0; i < num; i++)
+ {
+ if (i < num2)
+ {
+ if (i < b.Length)
+ {
+ StringExtensions.buffer[i] = b[i];
+ }
+ else
+ {
+ StringExtensions.buffer[i] = ' ';
+ }
+ }
+ else if (i < a.Length)
+ {
+ StringExtensions.buffer[i] = a[i];
+ }
+ }
+ return new string(StringExtensions.buffer, 0, num);
+ }
+}
diff --git a/Client/Assembly-CSharp/StringNames.cs b/Client/Assembly-CSharp/StringNames.cs
new file mode 100644
index 0000000..5c3c08b
--- /dev/null
+++ b/Client/Assembly-CSharp/StringNames.cs
@@ -0,0 +1,168 @@
+using System;
+
+public enum StringNames
+{
+ ExitButton,
+ BackButton,
+ AvailableGamesLabel,
+ CreateGameButton,
+ FindGameButton,
+ EnterCode,
+ GhostIgnoreTasks,
+ GhostDoTasks,
+ GhostImpostor,
+ ImpostorTask,
+ FakeTasks,
+ TaskComplete,
+ ExileTextSP,
+ ExileTextSN,
+ ExileTextPP,
+ ExileTextPN,
+ NoExileSkip,
+ NoExileTie,
+ ImpostorsRemainS,
+ ImpostorsRemainP,
+ Hallway,
+ Storage,
+ Cafeteria,
+ Reactor,
+ UpperEngine,
+ Nav,
+ Admin,
+ Electrical,
+ LifeSupp,
+ Shields,
+ MedBay,
+ Security,
+ Weapons,
+ LowerEngine,
+ Comms,
+ Decontamination,
+ Launchpad,
+ LockerRoom,
+ Laboratory,
+ Balcony,
+ Office,
+ Greenhouse,
+ DivertPowerTo,
+ AcceptDivertedPower,
+ SubmitScan,
+ PrimeShields,
+ FuelEngines,
+ ChartCourse,
+ StartReactor,
+ SwipeCard,
+ ClearAsteroids,
+ UploadData,
+ DownloadData,
+ InspectSample,
+ EmptyChute,
+ EmptyGarbage,
+ AlignEngineOutput,
+ FixWiring,
+ CalibrateDistributor,
+ UnlockManifolds,
+ ResetReactor,
+ FixLights,
+ FixComms,
+ RestoreOxy,
+ CleanO2Filter,
+ StabilizeSteering,
+ AssembleArtifact,
+ SortSamples,
+ MeasureWeather,
+ EnterIdCode,
+ HowToPlayText1,
+ HowToPlayText2,
+ HowToPlayText5,
+ HowToPlayText6,
+ HowToPlayText7,
+ HowToPlayText81,
+ HowToPlayText82,
+ NumImpostorsS,
+ NumImpostorsP,
+ Crewmate,
+ Impostor,
+ Victory,
+ Defeat,
+ CrewmatesDisconnected,
+ ImpostorDisconnected,
+ HowToPlayText41,
+ HowToPlayText42,
+ HowToPlayText43,
+ HowToPlayText44,
+ HowToPlayTextMap,
+ HowToPlayTextCrew1,
+ HowToPlayTextCrew2,
+ HowToPlayTextCrew3,
+ HowToPlayTextCrew4,
+ HowToPlayTextCrew5,
+ HowToPlayTextCrew6,
+ HowToPlayTextImp1,
+ HowToPlayTextImp2,
+ HowToPlayTextImp3,
+ HowToPlayTextImp4,
+ HowToPlayTextImp5,
+ HowToPlayTextImp6,
+ HowToPlayTextImp7,
+ SettingsGeneral,
+ SettingsControls,
+ SettingsSound,
+ SettingsGraphics,
+ SettingsData,
+ SettingsCensorChat,
+ SettingsMusic,
+ SettingsSFX,
+ SettingsOn,
+ SettingsOff,
+ SettingsSendTelemetry,
+ SettingsControlMode,
+ SettingsTouchMode,
+ SettingsJoystickMode,
+ SettingsKeyboardMode,
+ SettingsFullscreen,
+ SettingsResolution,
+ SettingsApply,
+ SettingsPersonalizeAds,
+ SettingsLanguage,
+ SettingsJoystickSize,
+ SettingsMouseMode,
+ PlayerColor,
+ PlayerHat,
+ PlayerSkin,
+ PlayerPet,
+ GameSettings,
+ GameRecommendedSettings,
+ GameCustomSettings,
+ GameMapName,
+ GameNumImpostors,
+ GameNumMeetings,
+ GameDiscussTime,
+ GameVotingTime,
+ GamePlayerSpeed,
+ GameCrewLight,
+ GameImpostorLight,
+ GameKillCooldown,
+ GameKillDistance,
+ GameCommonTasks,
+ GameLongTasks,
+ GameShortTasks,
+ MatchMapName,
+ MatchLanguage,
+ MatchImpostors,
+ MatchMaxPlayers,
+ Cancel,
+ Confirm,
+ Limit,
+ RoomCode,
+ LeaveGame,
+ ReturnToGame,
+ LocalHelp,
+ OnlineHelp,
+ SettingsVSync,
+ EmergencyCount,
+ EmergencyNotReady,
+ EmergencyDuringCrisis,
+ EmergencyRequested,
+ GameEmergencyCooldown
+}
diff --git a/Client/Assembly-CSharp/StringOption.cs b/Client/Assembly-CSharp/StringOption.cs
new file mode 100644
index 0000000..e2faa3e
--- /dev/null
+++ b/Client/Assembly-CSharp/StringOption.cs
@@ -0,0 +1,60 @@
+using System;
+using UnityEngine;
+
+public class StringOption : OptionBehaviour
+{
+ public TextRenderer TitleText;
+
+ public TextRenderer ValueText;
+
+ public string[] Values;
+
+ public int Value;
+
+ private int oldValue = -1;
+
+ public void OnEnable()
+ {
+ this.TitleText.Text = DestroyableSingleton<TranslationController>.Instance.GetString(this.Title, Array.Empty<object>());
+ this.ValueText.Text = this.Values[this.Value];
+ GameOptionsData gameOptions = PlayerControl.GameOptions;
+ StringNames title = this.Title;
+ if (title == StringNames.GameMapName)
+ {
+ this.Value = (int)gameOptions.MapId;
+ return;
+ }
+ if (title == StringNames.GameKillDistance)
+ {
+ this.Value = gameOptions.KillDistance;
+ return;
+ }
+ Debug.Log("Ono, unrecognized setting: " + this.Title);
+ }
+
+ private void FixedUpdate()
+ {
+ if (this.oldValue != this.Value)
+ {
+ this.oldValue = this.Value;
+ this.ValueText.Text = this.Values[this.Value];
+ }
+ }
+
+ public void Increase()
+ {
+ this.Value = Mathf.Clamp(this.Value + 1, 0, this.Values.Length - 1);
+ this.OnValueChanged(this);
+ }
+
+ public void Decrease()
+ {
+ this.Value = Mathf.Clamp(this.Value - 1, 0, this.Values.Length - 1);
+ this.OnValueChanged(this);
+ }
+
+ public override int GetInt()
+ {
+ return this.Value;
+ }
+}
diff --git a/Client/Assembly-CSharp/SubString.cs b/Client/Assembly-CSharp/SubString.cs
new file mode 100644
index 0000000..6270112
--- /dev/null
+++ b/Client/Assembly-CSharp/SubString.cs
@@ -0,0 +1,77 @@
+using System;
+
+public struct SubString
+{
+ public readonly int Start;
+
+ public readonly int Length;
+
+ public readonly string Source;
+
+ public SubString(string source, int start, int length)
+ {
+ this.Source = source;
+ this.Start = start;
+ this.Length = length;
+ }
+
+ public override string ToString()
+ {
+ return this.Source.Substring(this.Start, this.Length);
+ }
+
+ public int GetKvpValue()
+ {
+ int num = this.Start + this.Length;
+ for (int i = this.Start; i < num; i++)
+ {
+ if (this.Source[i] == '=')
+ {
+ i++;
+ return new SubString(this.Source, i, num - i).ToInt();
+ }
+ }
+ throw new InvalidCastException();
+ }
+
+ public int ToInt()
+ {
+ int num = 0;
+ int num2 = this.Start + this.Length;
+ bool flag = false;
+ for (int i = this.Start; i < num2; i++)
+ {
+ char c = this.Source[i];
+ if (c == '-')
+ {
+ flag = true;
+ }
+ else if (c >= '0' && c <= '9')
+ {
+ int num3 = (int)(c - '0');
+ num = 10 * num + num3;
+ }
+ }
+ if (!flag)
+ {
+ return num;
+ }
+ return -num;
+ }
+
+ public bool StartsWith(string v)
+ {
+ if (v.Length > this.Length)
+ {
+ return false;
+ }
+ for (int i = 0; i < v.Length; i++)
+ {
+ if (this.Source[i + this.Start] != v[i])
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/Client/Assembly-CSharp/SubStringReader.cs b/Client/Assembly-CSharp/SubStringReader.cs
new file mode 100644
index 0000000..3d90f31
--- /dev/null
+++ b/Client/Assembly-CSharp/SubStringReader.cs
@@ -0,0 +1,51 @@
+using System;
+
+public class SubStringReader
+{
+ private readonly string Source;
+
+ private int Position;
+
+ public SubStringReader(string source)
+ {
+ this.Source = source;
+ }
+
+ public SubString ReadLine()
+ {
+ int position = this.Position;
+ if (position >= this.Source.Length)
+ {
+ return default(SubString);
+ }
+ int num = this.Position;
+ int i = position;
+ while (i < this.Source.Length)
+ {
+ char c = this.Source[i];
+ if (c == '\r')
+ {
+ num = i - 1;
+ this.Position = i + 1;
+ if (i + 1 < this.Source.Length && this.Source[i + 1] == '\n')
+ {
+ this.Position = i + 2;
+ break;
+ }
+ break;
+ }
+ else
+ {
+ if (c == '\n')
+ {
+ num = i - 1;
+ this.Position = i + 1;
+ break;
+ }
+ this.Position++;
+ i++;
+ }
+ }
+ return new SubString(this.Source, position, num - position);
+ }
+}
diff --git a/Client/Assembly-CSharp/SurvCamera.cs b/Client/Assembly-CSharp/SurvCamera.cs
new file mode 100644
index 0000000..a5f0e1d
--- /dev/null
+++ b/Client/Assembly-CSharp/SurvCamera.cs
@@ -0,0 +1,28 @@
+using System;
+using PowerTools;
+using UnityEngine;
+
+public class SurvCamera : MonoBehaviour
+{
+ public SpriteAnim Image;
+
+ public float CamSize = 3f;
+
+ public float CamAspect = 1f;
+
+ public Vector3 Offset;
+
+ public AnimationClip OnAnim;
+
+ public AnimationClip OffAnim;
+
+ public void Awake()
+ {
+ this.Image = base.GetComponent<SpriteAnim>();
+ }
+
+ public void SetAnimation(bool on)
+ {
+ this.Image.Play(on ? this.OnAnim : this.OffAnim, 1f);
+ }
+}
diff --git a/Client/Assembly-CSharp/SurveillanceMinigame.cs b/Client/Assembly-CSharp/SurveillanceMinigame.cs
new file mode 100644
index 0000000..1fbde55
--- /dev/null
+++ b/Client/Assembly-CSharp/SurveillanceMinigame.cs
@@ -0,0 +1,140 @@
+using System;
+using System.Collections;
+using System.Linq;
+using UnityEngine;
+
+public class SurveillanceMinigame : Minigame
+{
+ public Camera CameraPrefab;
+
+ public GameObject Viewables;
+
+ public MeshRenderer[] ViewPorts;
+
+ public TextRenderer[] SabText;
+
+ private ShipRoom[] FilteredRooms;
+
+ private RenderTexture[] textures;
+
+ public MeshRenderer FillQuad;
+
+ public Material DefaultMaterial;
+
+ public Material StaticMaterial;
+
+ private bool isStatic;
+
+ public override void Begin(PlayerTask task)
+ {
+ base.Begin(task);
+ this.FilteredRooms = (from i in ShipStatus.Instance.AllRooms
+ where i.survCamera
+ select i).ToArray<ShipRoom>();
+ this.textures = new RenderTexture[this.FilteredRooms.Length];
+ for (int j = 0; j < this.FilteredRooms.Length; j++)
+ {
+ ShipRoom shipRoom = this.FilteredRooms[j];
+ Camera camera = UnityEngine.Object.Instantiate<Camera>(this.CameraPrefab);
+ camera.transform.SetParent(base.transform);
+ camera.transform.position = shipRoom.transform.position + shipRoom.survCamera.Offset;
+ camera.orthographicSize = shipRoom.survCamera.CamSize;
+ RenderTexture temporary = RenderTexture.GetTemporary((int)(256f * shipRoom.survCamera.CamAspect), 256, 16, RenderTextureFormat.ARGB32);
+ this.textures[j] = temporary;
+ camera.targetTexture = temporary;
+ this.ViewPorts[j].material.SetTexture("_MainTex", temporary);
+ }
+ if (!PlayerControl.LocalPlayer.Data.IsDead)
+ {
+ ShipStatus.Instance.RpcRepairSystem(SystemTypes.Security, 1);
+ }
+ }
+
+ public void Update()
+ {
+ if (this.isStatic && !PlayerTask.PlayerHasHudTask(PlayerControl.LocalPlayer))
+ {
+ this.isStatic = false;
+ for (int i = 0; i < this.ViewPorts.Length; i++)
+ {
+ this.ViewPorts[i].sharedMaterial = this.DefaultMaterial;
+ this.ViewPorts[i].material.SetTexture("_MainTex", this.textures[i]);
+ this.SabText[i].gameObject.SetActive(false);
+ }
+ return;
+ }
+ if (!this.isStatic && PlayerTask.PlayerHasHudTask(PlayerControl.LocalPlayer))
+ {
+ this.isStatic = true;
+ for (int j = 0; j < this.ViewPorts.Length; j++)
+ {
+ this.ViewPorts[j].sharedMaterial = this.StaticMaterial;
+ this.SabText[j].gameObject.SetActive(true);
+ }
+ }
+ }
+
+ protected override IEnumerator CoAnimateOpen()
+ {
+ this.Viewables.SetActive(false);
+ this.FillQuad.material.SetFloat("_Center", -5f);
+ this.FillQuad.material.SetColor("_Color2", Color.clear);
+ for (float timer = 0f; timer < 0.25f; timer += Time.deltaTime)
+ {
+ this.FillQuad.material.SetColor("_Color2", Color.Lerp(Color.clear, Color.black, timer / 0.25f));
+ yield return null;
+ }
+ this.FillQuad.material.SetColor("_Color2", Color.black);
+ this.Viewables.SetActive(true);
+ for (float timer = 0f; timer < 0.1f; timer += Time.deltaTime)
+ {
+ this.FillQuad.material.SetFloat("_Center", Mathf.Lerp(-5f, 0f, timer / 0.1f));
+ yield return null;
+ }
+ for (float timer = 0f; timer < 0.15f; timer += Time.deltaTime)
+ {
+ this.FillQuad.material.SetFloat("_Center", Mathf.Lerp(-3f, 0.4f, timer / 0.15f));
+ yield return null;
+ }
+ this.FillQuad.material.SetFloat("_Center", 0.4f);
+ yield break;
+ }
+
+ private IEnumerator CoAnimateClose()
+ {
+ for (float timer = 0f; timer < 0.1f; timer += Time.deltaTime)
+ {
+ this.FillQuad.material.SetFloat("_Center", Mathf.Lerp(0.4f, -5f, timer / 0.1f));
+ yield return null;
+ }
+ this.Viewables.SetActive(false);
+ for (float timer = 0f; timer < 0.3f; timer += Time.deltaTime)
+ {
+ this.FillQuad.material.SetColor("_Color2", Color.Lerp(Color.black, Color.clear, timer / 0.3f));
+ yield return null;
+ }
+ this.FillQuad.material.SetColor("_Color2", Color.clear);
+ yield break;
+ }
+
+ protected override IEnumerator CoDestroySelf()
+ {
+ yield return this.CoAnimateClose();
+ UnityEngine.Object.Destroy(base.gameObject);
+ yield break;
+ }
+
+ public override void Close()
+ {
+ base.Close();
+ ShipStatus.Instance.RpcRepairSystem(SystemTypes.Security, 2);
+ }
+
+ public void OnDestroy()
+ {
+ for (int i = 0; i < this.textures.Length; i++)
+ {
+ this.textures[i].Release();
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/SweepMinigame.cs b/Client/Assembly-CSharp/SweepMinigame.cs
new file mode 100644
index 0000000..6499a3f
--- /dev/null
+++ b/Client/Assembly-CSharp/SweepMinigame.cs
@@ -0,0 +1,123 @@
+using System;
+using UnityEngine;
+
+public class SweepMinigame : Minigame
+{
+ public SpriteRenderer[] Spinners;
+
+ public SpriteRenderer[] Shadows;
+
+ public SpriteRenderer[] Lights;
+
+ public HorizontalGauge[] Gauges;
+
+ private int spinnerIdx;
+
+ private float timer;
+
+ public float SpinRate = 45f;
+
+ private float initialTimer;
+
+ public AudioClip SpinningSound;
+
+ public AudioClip AcceptSound;
+
+ public AudioClip RejectSound;
+
+ public override void Begin(PlayerTask task)
+ {
+ base.Begin(task);
+ this.ResetGauges();
+ if (Constants.ShouldPlaySfx())
+ {
+ SoundManager.Instance.PlaySound(this.SpinningSound, true, 1f);
+ }
+ }
+
+ public override void Close()
+ {
+ SoundManager.Instance.StopSound(this.SpinningSound);
+ base.Close();
+ }
+
+ public void FixedUpdate()
+ {
+ float num = Mathf.Clamp(2f - this.timer / 30f, 1f, 2f);
+ this.timer += Time.fixedDeltaTime * num;
+ if (this.spinnerIdx < this.Spinners.Length)
+ {
+ float num2 = this.CalcXPerc();
+ this.Gauges[this.spinnerIdx].Value = ((num2 < 13f) ? 0.9f : 0.1f);
+ Quaternion localRotation = Quaternion.Euler(0f, 0f, this.timer * this.SpinRate);
+ this.Spinners[this.spinnerIdx].transform.localRotation = localRotation;
+ this.Shadows[this.spinnerIdx].transform.localRotation = localRotation;
+ this.Lights[this.spinnerIdx].enabled = (num2 < 13f);
+ }
+ for (int i = 0; i < this.Gauges.Length; i++)
+ {
+ HorizontalGauge horizontalGauge = this.Gauges[i];
+ if (i < this.spinnerIdx)
+ {
+ horizontalGauge.Value = 0.95f;
+ }
+ if (i > this.spinnerIdx)
+ {
+ horizontalGauge.Value = 0.05f;
+ }
+ horizontalGauge.Value += (Mathf.PerlinNoise((float)i, Time.time * 51f) - 0.5f) * 0.025f;
+ }
+ }
+
+ private float CalcXPerc()
+ {
+ int num = (int)(this.timer * this.SpinRate) % 360;
+ return (float)Mathf.Min(360 - num, num);
+ }
+
+ public void HitButton(int i)
+ {
+ if (i != this.spinnerIdx)
+ {
+ return;
+ }
+ if (this.CalcXPerc() < 13f)
+ {
+ if (Constants.ShouldPlaySfx())
+ {
+ SoundManager.Instance.PlaySound(this.AcceptSound, false, 1f);
+ }
+ this.Spinners[this.spinnerIdx].transform.localRotation = Quaternion.identity;
+ this.Shadows[this.spinnerIdx].transform.localRotation = Quaternion.identity;
+ this.spinnerIdx++;
+ this.timer = this.initialTimer;
+ if (this.spinnerIdx >= this.Gauges.Length)
+ {
+ this.MyNormTask.NextStep();
+ base.StartCoroutine(base.CoStartClose(0.75f));
+ return;
+ }
+ }
+ else
+ {
+ if (Constants.ShouldPlaySfx())
+ {
+ SoundManager.Instance.PlaySound(this.RejectSound, false, 1f);
+ }
+ this.ResetGauges();
+ }
+ }
+
+ private void ResetGauges()
+ {
+ this.spinnerIdx = 0;
+ this.timer = FloatRange.Next(1f, 3f);
+ this.initialTimer = this.timer;
+ for (int i = 0; i < this.Gauges.Length; i++)
+ {
+ this.Lights[i].enabled = false;
+ this.Spinners[i].transform.localRotation = Quaternion.Euler(0f, 0f, this.timer * this.SpinRate);
+ this.Shadows[i].transform.localRotation = Quaternion.Euler(0f, 0f, this.timer * this.SpinRate);
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/SwitchMinigame.cs b/Client/Assembly-CSharp/SwitchMinigame.cs
new file mode 100644
index 0000000..4013635
--- /dev/null
+++ b/Client/Assembly-CSharp/SwitchMinigame.cs
@@ -0,0 +1,97 @@
+using System;
+using UnityEngine;
+
+public class SwitchMinigame : Minigame
+{
+ public Color OnColor = Color.green;
+
+ public Color OffColor = new Color(0.1f, 0.3f, 0.1f);
+
+ private ShipStatus ship;
+
+ public SpriteRenderer[] switches;
+
+ public SpriteRenderer[] lights;
+
+ public RadioWaveBehaviour top;
+
+ public HorizontalGauge middle;
+
+ public FlatWaveBehaviour bottom;
+
+ public override void Begin(PlayerTask task)
+ {
+ this.ship = UnityEngine.Object.FindObjectOfType<ShipStatus>();
+ SwitchSystem switchSystem = this.ship.Systems[SystemTypes.Electrical] as SwitchSystem;
+ for (int i = 0; i < this.switches.Length; i++)
+ {
+ byte b = (byte)(1 << i);
+ int num = (int)(switchSystem.ActualSwitches & b);
+ this.lights[i].color = ((num == (int)(switchSystem.ExpectedSwitches & b)) ? this.OnColor : this.OffColor);
+ this.switches[i].flipY = (num >> i == 0);
+ }
+ }
+
+ public void FixedUpdate()
+ {
+ if (this.amClosing != Minigame.CloseState.None)
+ {
+ return;
+ }
+ int num = 0;
+ SwitchSystem switchSystem = this.ship.Systems[SystemTypes.Electrical] as SwitchSystem;
+ for (int i = 0; i < this.switches.Length; i++)
+ {
+ byte b = (byte)(1 << i);
+ int num2 = (int)(switchSystem.ActualSwitches & b);
+ if (num2 == (int)(switchSystem.ExpectedSwitches & b))
+ {
+ num++;
+ this.lights[i].color = this.OnColor;
+ }
+ else
+ {
+ this.lights[i].color = this.OffColor;
+ }
+ this.switches[i].flipY = (num2 >> i == 0);
+ }
+ float num3 = (float)num / (float)this.switches.Length;
+ this.bottom.Center = 0.47f * num3;
+ this.top.NoiseLevel = 1f - num3;
+ this.middle.Value = switchSystem.Level + (Mathf.PerlinNoise(0f, Time.time * 51f) - 0.5f) * 0.04f;
+ if (num == this.switches.Length)
+ {
+ base.StartCoroutine(base.CoStartClose(0.5f));
+ }
+ }
+
+ public void FlipSwitch(int switchIdx)
+ {
+ if (this.amClosing != Minigame.CloseState.None)
+ {
+ return;
+ }
+ int num = 0;
+ SwitchSystem switchSystem = this.ship.Systems[SystemTypes.Electrical] as SwitchSystem;
+ for (int i = 0; i < this.switches.Length; i++)
+ {
+ byte b = (byte)(1 << i);
+ if ((switchSystem.ActualSwitches & b) == (switchSystem.ExpectedSwitches & b))
+ {
+ num++;
+ }
+ }
+ if (num == this.switches.Length)
+ {
+ return;
+ }
+ ShipStatus.Instance.RpcRepairSystem(SystemTypes.Electrical, (int)((byte)switchIdx));
+ try
+ {
+ ((SabotageTask)this.MyTask).MarkContributed();
+ }
+ catch
+ {
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/SwitchSystem.cs b/Client/Assembly-CSharp/SwitchSystem.cs
new file mode 100644
index 0000000..0e400ad
--- /dev/null
+++ b/Client/Assembly-CSharp/SwitchSystem.cs
@@ -0,0 +1,107 @@
+using System;
+using Hazel;
+
+public class SwitchSystem : ISystemType, IActivatable
+{
+ public float Level
+ {
+ get
+ {
+ return (float)this.Value / 255f;
+ }
+ }
+
+ public bool IsActive
+ {
+ get
+ {
+ return this.ExpectedSwitches != this.ActualSwitches;
+ }
+ }
+
+ public const byte MaxValue = 255;
+
+ public const int NumSwitches = 5;
+
+ public const byte DamageSystem = 128;
+
+ public const byte SwitchesMask = 31;
+
+ public float DetoriorationTime = 0.03f;
+
+ public byte Value = byte.MaxValue;
+
+ private float timer;
+
+ public byte ExpectedSwitches;
+
+ public byte ActualSwitches;
+
+ public SwitchSystem()
+ {
+ Random random = new Random();
+ this.ExpectedSwitches = (byte)(random.Next() & 31);
+ this.ActualSwitches = this.ExpectedSwitches;
+ }
+
+ public bool Detoriorate(float deltaTime)
+ {
+ this.timer += deltaTime;
+ if (this.timer >= this.DetoriorationTime)
+ {
+ this.timer = 0f;
+ if (this.ExpectedSwitches != this.ActualSwitches)
+ {
+ if (this.Value > 0)
+ {
+ this.Value = (byte)Math.Max((int)(this.Value - 3), 0);
+ }
+ if (!SwitchSystem.HasTask<ElectricTask>())
+ {
+ PlayerControl.LocalPlayer.AddSystemTask(SystemTypes.Electrical);
+ }
+ }
+ else if (this.Value < 255)
+ {
+ this.Value = (byte)Math.Min((int)(this.Value + 3), 255);
+ }
+ }
+ return false;
+ }
+
+ public void RepairDamage(PlayerControl player, byte amount)
+ {
+ if (amount.HasBit(128))
+ {
+ this.ActualSwitches ^= (amount & 31);
+ return;
+ }
+ this.ActualSwitches ^= (byte)(1 << (int)amount);
+ }
+
+ public void Serialize(MessageWriter writer, bool initialState)
+ {
+ writer.Write(this.ExpectedSwitches);
+ writer.Write(this.ActualSwitches);
+ writer.Write(this.Value);
+ }
+
+ public void Deserialize(MessageReader reader, bool initialState)
+ {
+ this.ExpectedSwitches = reader.ReadByte();
+ this.ActualSwitches = reader.ReadByte();
+ this.Value = reader.ReadByte();
+ }
+
+ protected static bool HasTask<T>()
+ {
+ for (int i = PlayerControl.LocalPlayer.myTasks.Count - 1; i > 0; i--)
+ {
+ if (PlayerControl.LocalPlayer.myTasks[i] is T)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/Client/Assembly-CSharp/SystemConsole.cs b/Client/Assembly-CSharp/SystemConsole.cs
new file mode 100644
index 0000000..e0b4c10
--- /dev/null
+++ b/Client/Assembly-CSharp/SystemConsole.cs
@@ -0,0 +1,77 @@
+using System;
+using UnityEngine;
+
+public class SystemConsole : MonoBehaviour, IUsable
+{
+ public float UsableDistance
+ {
+ get
+ {
+ return this.usableDistance;
+ }
+ }
+
+ public float PercentCool
+ {
+ get
+ {
+ return 0f;
+ }
+ }
+
+ public float usableDistance = 1f;
+
+ public bool FreeplayOnly;
+
+ public SpriteRenderer Image;
+
+ public Minigame MinigamePrefab;
+
+ public void Start()
+ {
+ if (this.FreeplayOnly && !DestroyableSingleton<TutorialManager>.InstanceExists)
+ {
+ UnityEngine.Object.Destroy(base.gameObject);
+ }
+ }
+
+ public void SetOutline(bool on, bool mainTarget)
+ {
+ if (this.Image)
+ {
+ this.Image.material.SetFloat("_Outline", (float)(on ? 1 : 0));
+ this.Image.material.SetColor("_OutlineColor", Color.white);
+ this.Image.material.SetColor("_AddColor", mainTarget ? Color.white : Color.clear);
+ }
+ }
+
+ public float CanUse(GameData.PlayerInfo pc, out bool canUse, out bool couldUse)
+ {
+ float num = float.MaxValue;
+ PlayerControl @object = pc.Object;
+ couldUse = (pc.Object.CanMove && (!pc.IsDead || !(this.MinigamePrefab is EmergencyMinigame)));
+ canUse = couldUse;
+ if (canUse)
+ {
+ num = Vector2.Distance(@object.GetTruePosition(), base.transform.position);
+ canUse &= (num <= this.UsableDistance);
+ }
+ return num;
+ }
+
+ public void Use()
+ {
+ bool flag;
+ bool flag2;
+ this.CanUse(PlayerControl.LocalPlayer.Data, out flag, out flag2);
+ if (!flag)
+ {
+ return;
+ }
+ PlayerControl.LocalPlayer.NetTransform.Halt();
+ Minigame minigame = UnityEngine.Object.Instantiate<Minigame>(this.MinigamePrefab);
+ minigame.transform.SetParent(Camera.main.transform, false);
+ minigame.transform.localPosition = new Vector3(0f, 0f, -50f);
+ minigame.Begin(null);
+ }
+}
diff --git a/Client/Assembly-CSharp/SystemTypeHelpers.cs b/Client/Assembly-CSharp/SystemTypeHelpers.cs
new file mode 100644
index 0000000..d462322
--- /dev/null
+++ b/Client/Assembly-CSharp/SystemTypeHelpers.cs
@@ -0,0 +1,7 @@
+using System;
+using System.Linq;
+
+public static class SystemTypeHelpers
+{
+ public static readonly SystemTypes[] AllTypes = Enum.GetValues(typeof(SystemTypes)).Cast<SystemTypes>().ToArray<SystemTypes>();
+}
diff --git a/Client/Assembly-CSharp/SystemTypes.cs b/Client/Assembly-CSharp/SystemTypes.cs
new file mode 100644
index 0000000..f536ac2
--- /dev/null
+++ b/Client/Assembly-CSharp/SystemTypes.cs
@@ -0,0 +1,30 @@
+using System;
+
+public enum SystemTypes : byte
+{
+ Hallway,
+ Storage,
+ Cafeteria,
+ Reactor,
+ UpperEngine,
+ Nav,
+ Admin,
+ Electrical,
+ LifeSupp,
+ Shields,
+ MedBay,
+ Security,
+ Weapons,
+ LowerEngine,
+ Comms,
+ ShipTasks,
+ Doors,
+ Sabotage,
+ Decontamination,
+ Launchpad,
+ LockerRoom,
+ Laboratory,
+ Balcony,
+ Office,
+ Greenhouse
+}
diff --git a/Client/Assembly-CSharp/TabButton.cs b/Client/Assembly-CSharp/TabButton.cs
new file mode 100644
index 0000000..0d6efb5
--- /dev/null
+++ b/Client/Assembly-CSharp/TabButton.cs
@@ -0,0 +1,10 @@
+using System;
+using UnityEngine;
+
+[Serializable]
+public class TabButton
+{
+ public SpriteRenderer Button;
+
+ public GameObject Tab;
+}
diff --git a/Client/Assembly-CSharp/TabGroup.cs b/Client/Assembly-CSharp/TabGroup.cs
new file mode 100644
index 0000000..066e250
--- /dev/null
+++ b/Client/Assembly-CSharp/TabGroup.cs
@@ -0,0 +1,25 @@
+using System;
+using UnityEngine;
+
+public class TabGroup : MonoBehaviour
+{
+ public SpriteRenderer Button;
+
+ public ButtonRolloverHandler Rollover;
+
+ public GameObject Content;
+
+ internal void Close()
+ {
+ this.Button.color = Color.white;
+ this.Rollover.OutColor = Color.white;
+ this.Content.SetActive(false);
+ }
+
+ internal void Open()
+ {
+ this.Button.color = Color.green;
+ this.Rollover.OutColor = Color.green;
+ this.Content.SetActive(true);
+ }
+}
diff --git a/Client/Assembly-CSharp/TaskAddButton.cs b/Client/Assembly-CSharp/TaskAddButton.cs
new file mode 100644
index 0000000..60e54fc
--- /dev/null
+++ b/Client/Assembly-CSharp/TaskAddButton.cs
@@ -0,0 +1,109 @@
+using System;
+using UnityEngine;
+
+public class TaskAddButton : MonoBehaviour
+{
+ public TextRenderer Text;
+
+ public SpriteRenderer Overlay;
+
+ public Sprite CheckImage;
+
+ public Sprite ExImage;
+
+ public PlayerTask MyTask;
+
+ public bool ImpostorTask;
+
+ public void Start()
+ {
+ if (this.ImpostorTask)
+ {
+ GameData.PlayerInfo data = PlayerControl.LocalPlayer.Data;
+ this.Overlay.enabled = data.IsImpostor;
+ this.Overlay.sprite = this.CheckImage;
+ return;
+ }
+ PlayerTask playerTask = this.FindTaskByType();
+ if (playerTask)
+ {
+ this.Overlay.enabled = true;
+ this.Overlay.sprite = (playerTask.IsComplete ? this.CheckImage : this.ExImage);
+ return;
+ }
+ this.Overlay.enabled = false;
+ }
+
+ public void AddTask()
+ {
+ if (this.ImpostorTask)
+ {
+ GameData.PlayerInfo data = PlayerControl.LocalPlayer.Data;
+ if (data.IsImpostor)
+ {
+ PlayerControl.LocalPlayer.RemoveInfected();
+ this.Overlay.enabled = false;
+ return;
+ }
+ PlayerControl.LocalPlayer.RpcSetInfected(new GameData.PlayerInfo[]
+ {
+ data
+ });
+ this.Overlay.enabled = true;
+ return;
+ }
+ else
+ {
+ PlayerTask playerTask = this.FindTaskByType();
+ if (!playerTask)
+ {
+ PlayerTask playerTask2 = UnityEngine.Object.Instantiate<PlayerTask>(this.MyTask, PlayerControl.LocalPlayer.transform);
+ PlayerTask playerTask3 = playerTask2;
+ PlayerControl localPlayer = PlayerControl.LocalPlayer;
+ uint taskIdCount = localPlayer.TaskIdCount;
+ localPlayer.TaskIdCount = taskIdCount + 1U;
+ playerTask3.Id = taskIdCount;
+ playerTask2.Owner = PlayerControl.LocalPlayer;
+ playerTask2.Initialize();
+ PlayerControl.LocalPlayer.myTasks.Add(playerTask2);
+ GameData.Instance.TutOnlyAddTask(PlayerControl.LocalPlayer.PlayerId, playerTask2.Id);
+ this.Overlay.sprite = this.ExImage;
+ this.Overlay.enabled = true;
+ return;
+ }
+ PlayerControl.LocalPlayer.RemoveTask(playerTask);
+ this.Overlay.enabled = false;
+ return;
+ }
+ }
+
+ private PlayerTask FindTaskByType()
+ {
+ for (int i = PlayerControl.LocalPlayer.myTasks.Count - 1; i > -1; i--)
+ {
+ PlayerTask playerTask = PlayerControl.LocalPlayer.myTasks[i];
+ if (playerTask.TaskType == this.MyTask.TaskType)
+ {
+ if (playerTask.TaskType == TaskTypes.DivertPower)
+ {
+ if (((DivertPowerTask)playerTask).TargetSystem == ((DivertPowerTask)this.MyTask).TargetSystem)
+ {
+ return playerTask;
+ }
+ }
+ else
+ {
+ if (playerTask.TaskType != TaskTypes.UploadData)
+ {
+ return playerTask;
+ }
+ if (playerTask.StartAt == this.MyTask.StartAt)
+ {
+ return playerTask;
+ }
+ }
+ }
+ }
+ return null;
+ }
+}
diff --git a/Client/Assembly-CSharp/TaskAdderGame.cs b/Client/Assembly-CSharp/TaskAdderGame.cs
new file mode 100644
index 0000000..b40a715
--- /dev/null
+++ b/Client/Assembly-CSharp/TaskAdderGame.cs
@@ -0,0 +1,168 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using UnityEngine;
+
+public class TaskAdderGame : Minigame
+{
+ public TextRenderer PathText;
+
+ public TaskFolder RootFolderPrefab;
+
+ public TaskAddButton TaskPrefab;
+
+ public Transform TaskParent;
+
+ public List<TaskFolder> Heirarchy = new List<TaskFolder>();
+
+ public List<Transform> ActiveItems = new List<Transform>();
+
+ public TaskAddButton InfectedButton;
+
+ public float folderWidth;
+
+ public float fileWidth;
+
+ public float lineWidth;
+
+ public float lineHeight;
+
+ private TaskFolder Root;
+
+ public override void Begin(PlayerTask t)
+ {
+ base.Begin(t);
+ this.Root = UnityEngine.Object.Instantiate<TaskFolder>(this.RootFolderPrefab, base.transform);
+ this.Root.gameObject.SetActive(false);
+ Dictionary<SystemTypes, TaskFolder> folders = new Dictionary<SystemTypes, TaskFolder>();
+ this.PopulateRoot(this.Root, folders, ShipStatus.Instance.CommonTasks);
+ this.PopulateRoot(this.Root, folders, ShipStatus.Instance.LongTasks);
+ this.PopulateRoot(this.Root, folders, ShipStatus.Instance.NormalTasks);
+ this.Root.SubFolders = (from f in this.Root.SubFolders
+ orderby f.FolderName
+ select f).ToList<TaskFolder>();
+ this.ShowFolder(this.Root);
+ }
+
+ private void PopulateRoot(TaskFolder rootFolder, Dictionary<SystemTypes, TaskFolder> folders, NormalPlayerTask[] taskList)
+ {
+ foreach (NormalPlayerTask normalPlayerTask in taskList)
+ {
+ SystemTypes systemTypes = normalPlayerTask.StartAt;
+ if (normalPlayerTask is DivertPowerTask)
+ {
+ systemTypes = ((DivertPowerTask)normalPlayerTask).TargetSystem;
+ }
+ if (systemTypes == SystemTypes.LowerEngine)
+ {
+ systemTypes = SystemTypes.UpperEngine;
+ }
+ TaskFolder taskFolder;
+ if (!folders.TryGetValue(systemTypes, out taskFolder))
+ {
+ taskFolder = (folders[systemTypes] = UnityEngine.Object.Instantiate<TaskFolder>(this.RootFolderPrefab, base.transform));
+ taskFolder.gameObject.SetActive(false);
+ if (systemTypes == SystemTypes.UpperEngine)
+ {
+ taskFolder.FolderName = "Engines";
+ }
+ else
+ {
+ taskFolder.FolderName = DestroyableSingleton<TranslationController>.Instance.GetString(systemTypes);
+ }
+ rootFolder.SubFolders.Add(taskFolder);
+ }
+ taskFolder.Children.Add(normalPlayerTask);
+ }
+ }
+
+ public void GoToRoot()
+ {
+ this.Heirarchy.Clear();
+ this.ShowFolder(this.Root);
+ }
+
+ public void GoUpOne()
+ {
+ if (this.Heirarchy.Count > 1)
+ {
+ TaskFolder taskFolder = this.Heirarchy[this.Heirarchy.Count - 2];
+ this.Heirarchy.RemoveAt(this.Heirarchy.Count - 1);
+ this.Heirarchy.RemoveAt(this.Heirarchy.Count - 1);
+ this.ShowFolder(taskFolder);
+ }
+ }
+
+ public void ShowFolder(TaskFolder taskFolder)
+ {
+ StringBuilder stringBuilder = new StringBuilder(64);
+ this.Heirarchy.Add(taskFolder);
+ for (int i = 0; i < this.Heirarchy.Count; i++)
+ {
+ stringBuilder.Append(this.Heirarchy[i].FolderName);
+ stringBuilder.Append("\\");
+ }
+ this.PathText.Text = stringBuilder.ToString();
+ for (int j = 0; j < this.ActiveItems.Count; j++)
+ {
+ UnityEngine.Object.Destroy(this.ActiveItems[j].gameObject);
+ }
+ this.ActiveItems.Clear();
+ float num = 0f;
+ float num2 = 0f;
+ for (int k = 0; k < taskFolder.SubFolders.Count; k++)
+ {
+ TaskFolder taskFolder2 = UnityEngine.Object.Instantiate<TaskFolder>(taskFolder.SubFolders[k], this.TaskParent);
+ taskFolder2.gameObject.SetActive(true);
+ taskFolder2.Parent = this;
+ taskFolder2.transform.localPosition = new Vector3(num, num2, 0f);
+ taskFolder2.transform.localScale = Vector3.one;
+ num += this.folderWidth;
+ if (num > this.lineWidth)
+ {
+ num = 0f;
+ num2 += this.lineHeight;
+ }
+ this.ActiveItems.Add(taskFolder2.transform);
+ }
+ List<PlayerTask> list = (from t in taskFolder.Children
+ orderby t.TaskType.ToString()
+ select t).ToList<PlayerTask>();
+ for (int l = 0; l < list.Count; l++)
+ {
+ TaskAddButton taskAddButton = UnityEngine.Object.Instantiate<TaskAddButton>(this.TaskPrefab);
+ taskAddButton.MyTask = list[l];
+ if (taskAddButton.MyTask.TaskType == TaskTypes.DivertPower)
+ {
+ SystemTypes targetSystem = ((DivertPowerTask)taskAddButton.MyTask).TargetSystem;
+ taskAddButton.Text.Text = DestroyableSingleton<TranslationController>.Instance.GetString(StringNames.DivertPowerTo, Array.Empty<object>()) + " " + DestroyableSingleton<TranslationController>.Instance.GetString(targetSystem);
+ }
+ else
+ {
+ taskAddButton.Text.Text = DestroyableSingleton<TranslationController>.Instance.GetString(taskAddButton.MyTask.TaskType);
+ }
+ this.AddFileAsChild(taskAddButton, ref num, ref num2);
+ }
+ if (this.Heirarchy.Count == 1)
+ {
+ TaskAddButton taskAddButton2 = UnityEngine.Object.Instantiate<TaskAddButton>(this.InfectedButton);
+ taskAddButton2.Text.Text = "Be_Impostor.exe";
+ this.AddFileAsChild(taskAddButton2, ref num, ref num2);
+ }
+ }
+
+ private void AddFileAsChild(TaskAddButton item, ref float xCursor, ref float yCursor)
+ {
+ item.transform.SetParent(this.TaskParent);
+ item.transform.localPosition = new Vector3(xCursor, yCursor, 0f);
+ item.transform.localScale = Vector3.one;
+ xCursor += this.fileWidth;
+ if (xCursor > this.lineWidth)
+ {
+ xCursor = 0f;
+ yCursor -= this.lineHeight;
+ }
+ this.ActiveItems.Add(item.transform);
+ }
+}
diff --git a/Client/Assembly-CSharp/TaskFolder.cs b/Client/Assembly-CSharp/TaskFolder.cs
new file mode 100644
index 0000000..91f3f08
--- /dev/null
+++ b/Client/Assembly-CSharp/TaskFolder.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class TaskFolder : MonoBehaviour
+{
+ public string FolderName;
+
+ public TextRenderer Text;
+
+ public TaskAdderGame Parent;
+
+ public List<TaskFolder> SubFolders = new List<TaskFolder>();
+
+ public List<PlayerTask> Children = new List<PlayerTask>();
+
+ public void Start()
+ {
+ this.Text.Text = this.FolderName;
+ }
+
+ public void OnClick()
+ {
+ this.Parent.ShowFolder(this);
+ }
+
+ internal List<TaskFolder> OrderBy()
+ {
+ throw new NotImplementedException();
+ }
+}
diff --git a/Client/Assembly-CSharp/TaskPanelBehaviour.cs b/Client/Assembly-CSharp/TaskPanelBehaviour.cs
new file mode 100644
index 0000000..65fb0fd
--- /dev/null
+++ b/Client/Assembly-CSharp/TaskPanelBehaviour.cs
@@ -0,0 +1,52 @@
+using System;
+using UnityEngine;
+
+public class TaskPanelBehaviour : MonoBehaviour
+{
+ public Vector3 OpenPosition;
+
+ public Vector3 ClosedPosition;
+
+ public SpriteRenderer background;
+
+ public SpriteRenderer tab;
+
+ public TextRenderer TaskText;
+
+ public bool open;
+
+ private float timer;
+
+ public float Duration;
+
+ private void Update()
+ {
+ this.background.transform.localScale = new Vector3(this.TaskText.Width + 0.2f, this.TaskText.Height + 0.2f, 1f);
+ Vector3 vector = this.background.sprite.bounds.extents;
+ vector.y = -vector.y;
+ vector = vector.Mul(this.background.transform.localScale);
+ this.background.transform.localPosition = vector;
+ Vector3 vector2 = this.tab.sprite.bounds.extents;
+ vector2 = vector2.Mul(this.tab.transform.localScale);
+ vector2.y = -vector2.y;
+ vector2.x += vector.x * 2f;
+ this.tab.transform.localPosition = vector2;
+ this.ClosedPosition.y = (this.OpenPosition.y = 0.6f);
+ this.ClosedPosition.x = -this.background.sprite.bounds.size.x * this.background.transform.localScale.x;
+ if (this.open)
+ {
+ this.timer = Mathf.Min(1f, this.timer + Time.deltaTime / this.Duration);
+ }
+ else
+ {
+ this.timer = Mathf.Max(0f, this.timer - Time.deltaTime / this.Duration);
+ }
+ Vector3 relativePos = new Vector3(Mathf.SmoothStep(this.ClosedPosition.x, this.OpenPosition.x, this.timer), Mathf.SmoothStep(this.ClosedPosition.y, this.OpenPosition.y, this.timer), this.OpenPosition.z);
+ base.transform.localPosition = AspectPosition.ComputePosition(AspectPosition.EdgeAlignments.LeftTop, relativePos);
+ }
+
+ public void ToggleOpen()
+ {
+ this.open = !this.open;
+ }
+}
diff --git a/Client/Assembly-CSharp/TaskSet.cs b/Client/Assembly-CSharp/TaskSet.cs
new file mode 100644
index 0000000..9585c7b
--- /dev/null
+++ b/Client/Assembly-CSharp/TaskSet.cs
@@ -0,0 +1,9 @@
+using System;
+
+[Serializable]
+public class TaskSet
+{
+ public TaskTypes taskType;
+
+ public IntRange taskStep = new IntRange(0, 0);
+}
diff --git a/Client/Assembly-CSharp/TaskTypes.cs b/Client/Assembly-CSharp/TaskTypes.cs
new file mode 100644
index 0000000..67d35db
--- /dev/null
+++ b/Client/Assembly-CSharp/TaskTypes.cs
@@ -0,0 +1,31 @@
+using System;
+
+public enum TaskTypes
+{
+ SubmitScan,
+ PrimeShields,
+ FuelEngines,
+ ChartCourse,
+ StartReactor,
+ SwipeCard,
+ ClearAsteroids,
+ UploadData,
+ InspectSample,
+ EmptyChute,
+ EmptyGarbage,
+ AlignEngineOutput,
+ FixWiring,
+ CalibrateDistributor,
+ DivertPower,
+ UnlockManifolds,
+ ResetReactor,
+ FixLights,
+ CleanO2Filter,
+ FixComms,
+ RestoreOxy,
+ StabilizeSteering,
+ AssembleArtifact,
+ SortSamples,
+ MeasureWeather,
+ EnterIdCode
+}
diff --git a/Client/Assembly-CSharp/TaskTypesHelpers.cs b/Client/Assembly-CSharp/TaskTypesHelpers.cs
new file mode 100644
index 0000000..ba8eda0
--- /dev/null
+++ b/Client/Assembly-CSharp/TaskTypesHelpers.cs
@@ -0,0 +1,7 @@
+using System;
+using System.Linq;
+
+public static class TaskTypesHelpers
+{
+ public static readonly TaskTypes[] AllTypes = Enum.GetValues(typeof(TaskTypes)).Cast<TaskTypes>().ToArray<TaskTypes>();
+}
diff --git a/Client/Assembly-CSharp/TempData.cs b/Client/Assembly-CSharp/TempData.cs
new file mode 100644
index 0000000..46d333e
--- /dev/null
+++ b/Client/Assembly-CSharp/TempData.cs
@@ -0,0 +1,74 @@
+using System;
+using System.Collections.Generic;
+
+public static class TempData
+{
+ public static DeathReason LastDeathReason;
+
+ public static GameOverReason EndReason = GameOverReason.HumansByTask;
+
+ public static bool showAd;
+
+ public static List<WinningPlayerData> winners = new List<WinningPlayerData>
+ {
+ new WinningPlayerData
+ {
+ Name = "WWWWWWWWWW",
+ ColorId = 0,
+ SkinId = 0U,
+ IsDead = true
+ },
+ new WinningPlayerData
+ {
+ Name = "WWWWWWWWWW",
+ ColorId = 1,
+ SkinId = 1U,
+ IsDead = true
+ },
+ new WinningPlayerData
+ {
+ Name = "WWWWWWWWWW",
+ ColorId = 2,
+ SkinId = 2U,
+ IsDead = true
+ },
+ new WinningPlayerData
+ {
+ Name = "WWWWWWWWWW",
+ ColorId = 3,
+ SkinId = 0U
+ },
+ new WinningPlayerData
+ {
+ Name = "WWWWWWWWWW",
+ ColorId = 4,
+ SkinId = 1U
+ },
+ new WinningPlayerData
+ {
+ Name = "WWWWWWWWWW",
+ ColorId = 5,
+ SkinId = 2U
+ },
+ new WinningPlayerData
+ {
+ Name = "WWWWWWWWWW",
+ ColorId = 6
+ },
+ new WinningPlayerData
+ {
+ Name = "WWWWWWWWWW",
+ ColorId = 7
+ },
+ new WinningPlayerData
+ {
+ Name = "WWWWWWWWWW",
+ ColorId = 8
+ }
+ };
+
+ public static bool DidHumansWin(GameOverReason reason)
+ {
+ return reason == GameOverReason.HumansByTask || reason == GameOverReason.HumansByVote;
+ }
+}
diff --git a/Client/Assembly-CSharp/TextBox.cs b/Client/Assembly-CSharp/TextBox.cs
new file mode 100644
index 0000000..29e98ab
--- /dev/null
+++ b/Client/Assembly-CSharp/TextBox.cs
@@ -0,0 +1,257 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using UnityEngine;
+using UnityEngine.UI;
+
+public class TextBox : MonoBehaviour, IFocusHolder
+{
+ public float TextHeight
+ {
+ get
+ {
+ return this.outputText.Height;
+ }
+ }
+
+ public static readonly HashSet<char> SymbolChars = new HashSet<char>
+ {
+ '?',
+ '!',
+ ',',
+ '.',
+ '\'',
+ ':',
+ ';',
+ '(',
+ ')',
+ '/',
+ '\\',
+ '%',
+ '^',
+ '&',
+ '-',
+ '='
+ };
+
+ public string text;
+
+ private string compoText = "";
+
+ public int characterLimit = -1;
+
+ [SerializeField]
+ private TextRenderer outputText;
+
+ public SpriteRenderer Background;
+
+ public MeshRenderer Pipe;
+
+ private float pipeBlinkTimer;
+
+ public bool ClearOnFocus;
+
+ public bool ForceUppercase;
+
+ public Button.ButtonClickedEvent OnEnter;
+
+ public Button.ButtonClickedEvent OnChange;
+
+ public Button.ButtonClickedEvent OnFocusLost;
+
+ private TouchScreenKeyboard keyboard;
+
+ public bool AllowSymbols;
+
+ public bool IpMode;
+
+ private Collider2D[] colliders;
+
+ private bool hasFocus;
+
+ private StringBuilder tempTxt = new StringBuilder();
+
+ public void Start()
+ {
+ this.colliders = base.GetComponents<Collider2D>();
+ DestroyableSingleton<PassiveButtonManager>.Instance.RegisterOne(this);
+ if (this.Pipe)
+ {
+ this.Pipe.enabled = false;
+ }
+ }
+
+ public void OnDestroy()
+ {
+ if (this.keyboard != null)
+ {
+ this.keyboard.active = false;
+ this.keyboard = null;
+ }
+ if (DestroyableSingleton<PassiveButtonManager>.InstanceExists)
+ {
+ DestroyableSingleton<PassiveButtonManager>.Instance.RemoveOne(this);
+ }
+ }
+
+ public void Clear()
+ {
+ this.SetText(string.Empty, string.Empty);
+ }
+
+ public void Update()
+ {
+ if (!this.hasFocus)
+ {
+ return;
+ }
+ string inputString = Input.inputString;
+ if (inputString.Length > 0 || this.compoText != Input.compositionString)
+ {
+ if (this.text == null || this.text == "Enter Name")
+ {
+ this.text = "";
+ }
+ this.SetText(this.text + inputString, Input.compositionString);
+ }
+ if (this.Pipe && this.hasFocus)
+ {
+ this.pipeBlinkTimer += Time.deltaTime * 2f;
+ this.Pipe.enabled = ((int)this.pipeBlinkTimer % 2 == 0);
+ }
+ }
+
+ public void GiveFocus()
+ {
+ Input.imeCompositionMode = IMECompositionMode.On;
+ if (this.hasFocus)
+ {
+ return;
+ }
+ if (this.ClearOnFocus)
+ {
+ this.text = string.Empty;
+ this.compoText = string.Empty;
+ this.outputText.Text = string.Empty;
+ }
+ this.hasFocus = true;
+ if (TouchScreenKeyboard.isSupported)
+ {
+ this.keyboard = TouchScreenKeyboard.Open(this.text);
+ }
+ if (this.Background)
+ {
+ this.Background.color = Color.green;
+ }
+ this.pipeBlinkTimer = 0f;
+ if (this.Pipe)
+ {
+ this.Pipe.transform.localPosition = this.outputText.CursorPos;
+ }
+ }
+
+ public void LoseFocus()
+ {
+ if (!this.hasFocus)
+ {
+ return;
+ }
+ Input.imeCompositionMode = IMECompositionMode.Off;
+ if (this.compoText.Length > 0)
+ {
+ this.SetText(this.text + this.compoText, "");
+ this.compoText = string.Empty;
+ }
+ this.hasFocus = false;
+ if (this.keyboard != null)
+ {
+ this.keyboard.active = false;
+ this.keyboard = null;
+ }
+ if (this.Background)
+ {
+ this.Background.color = Color.white;
+ }
+ if (this.Pipe)
+ {
+ this.Pipe.enabled = false;
+ }
+ this.OnFocusLost.Invoke();
+ }
+
+ public bool CheckCollision(Vector2 pt)
+ {
+ for (int i = 0; i < this.colliders.Length; i++)
+ {
+ if (this.colliders[i].OverlapPoint(pt))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void SetText(string input, string inputCompo = "")
+ {
+ bool flag = false;
+ char c = ' ';
+ this.tempTxt.Clear();
+ foreach (char c2 in input)
+ {
+ if (c != ' ' || c2 != ' ')
+ {
+ if (c2 == '\r' || c2 == '\n')
+ {
+ flag = true;
+ }
+ if (c2 == '\b')
+ {
+ this.tempTxt.Length = Math.Max(this.tempTxt.Length - 1, 0);
+ }
+ if (this.ForceUppercase)
+ {
+ c2 = char.ToUpperInvariant(c2);
+ }
+ if (this.IsCharAllowed(c2))
+ {
+ this.tempTxt.Append(c2);
+ c = c2;
+ }
+ }
+ }
+ if (this.characterLimit > 0)
+ {
+ this.tempTxt.Length = Math.Min(this.tempTxt.Length, this.characterLimit);
+ }
+ input = this.tempTxt.ToString();
+ if (!input.Equals(this.text) || !inputCompo.Equals(this.compoText))
+ {
+ this.text = input;
+ this.compoText = inputCompo;
+ this.outputText.Text = this.text + "[FF0000FF]" + this.compoText + "[]";
+ this.outputText.RefreshMesh();
+ if (this.keyboard != null)
+ {
+ this.keyboard.text = this.text;
+ }
+ this.OnChange.Invoke();
+ }
+ if (flag)
+ {
+ this.OnEnter.Invoke();
+ }
+ if (this.Pipe)
+ {
+ this.Pipe.transform.localPosition = this.outputText.CursorPos;
+ }
+ }
+
+ public bool IsCharAllowed(char i)
+ {
+ if (this.IpMode)
+ {
+ return (i >= '0' && i <= '9') || i == '.';
+ }
+ return i == ' ' || (i >= 'A' && i <= 'Z') || (i >= 'a' && i <= 'z') || (i >= '0' && i <= '9') || (i >= 'À' && i <= 'ÿ') || (i >= 'Ѐ' && i <= 'џ') || (i >= 'ㄱ' && i <= 'ㆎ') || (i >= '가' && i <= '힣') || (this.AllowSymbols && TextBox.SymbolChars.Contains(i));
+ }
+}
diff --git a/Client/Assembly-CSharp/TextController.cs b/Client/Assembly-CSharp/TextController.cs
new file mode 100644
index 0000000..c98db4e
--- /dev/null
+++ b/Client/Assembly-CSharp/TextController.cs
@@ -0,0 +1,130 @@
+using System;
+using UnityEngine;
+
+[RequireComponent(typeof(MeshFilter))]
+[RequireComponent(typeof(MeshRenderer))]
+public class TextController : MonoBehaviour
+{
+ public float Scale = 1f;
+
+ [Multiline]
+ public string Text;
+
+ private string displaying;
+
+ [HideInInspector]
+ private Texture2D texture;
+
+ [HideInInspector]
+ private Texture2D colorTexture;
+
+ private MeshRenderer rend;
+
+ private float _scale = float.NegativeInfinity;
+
+ public Color Color = Color.white;
+
+ private Color lastColor;
+
+ public Vector3 Offset;
+
+ public bool topAligned;
+
+ public void Update()
+ {
+ if (!this.rend)
+ {
+ this.rend = base.GetComponent<MeshRenderer>();
+ }
+ if (string.IsNullOrEmpty(this.Text))
+ {
+ this.rend.enabled = false;
+ return;
+ }
+ if (this.displaying == null || this.displaying.GetHashCode() != this.Text.GetHashCode() || this.Color != this.lastColor)
+ {
+ int num = 0;
+ int num2 = 0;
+ int num3 = 1;
+ for (int i = 0; i < this.Text.Length; i++)
+ {
+ if (this.Text[i] == '\n')
+ {
+ num2 = 0;
+ num3++;
+ }
+ else
+ {
+ num2++;
+ if (num2 > num)
+ {
+ num = num2;
+ }
+ }
+ }
+ if (!this.texture || !this.colorTexture)
+ {
+ if (!this.texture)
+ {
+ this.texture = new Texture2D(num, num3, TextureFormat.ARGB32, false);
+ this.texture.filterMode = FilterMode.Point;
+ this.texture.wrapMode = TextureWrapMode.Clamp;
+ }
+ if (!this.colorTexture)
+ {
+ this.colorTexture = new Texture2D(num, num3, TextureFormat.ARGB32, false);
+ this.colorTexture.filterMode = FilterMode.Point;
+ this.colorTexture.wrapMode = TextureWrapMode.Clamp;
+ }
+ }
+ else if (this.texture.width != num || this.texture.height != num3)
+ {
+ this.texture.Resize(num, num3, TextureFormat.ARGB32, false);
+ this.colorTexture.Resize(num, num3, TextureFormat.ARGB32, false);
+ }
+ Color[] array = new Color[num * num3];
+ array.SetAll(this.Color);
+ this.colorTexture.SetPixels(array);
+ array.SetAll(new Color(0.125f, 0f, 0f));
+ this.texture.SetPixels(array);
+ int num4 = 0;
+ int num5 = this.texture.height - 1;
+ Color color = this.Color;
+ for (int j = 0; j < this.Text.Length; j++)
+ {
+ char c = this.Text[j];
+ if (c != '\r')
+ {
+ if (c == '\n')
+ {
+ num4 = 0;
+ num5--;
+ }
+ else
+ {
+ this.texture.SetPixel(num4, num5, new Color((float)c / 256f, 0f, 0f));
+ this.colorTexture.SetPixel(num4, num5, color);
+ num4++;
+ }
+ }
+ }
+ this.texture.Apply(false, false);
+ this.colorTexture.Apply(false, false);
+ this.rend.enabled = true;
+ this.rend.material.SetTexture("_InputTex", this.texture);
+ this.rend.material.SetTexture("_ColorTex", this.colorTexture);
+ this._scale = float.NegativeInfinity;
+ this.displaying = this.Text;
+ this.lastColor = this.Color;
+ }
+ if (this._scale != this.Scale)
+ {
+ this._scale = this.Scale;
+ base.transform.localScale = new Vector3((float)this.texture.width, (float)this.texture.height, 1f) * this.Scale;
+ if (this.topAligned)
+ {
+ base.transform.localPosition = this.Offset + new Vector3((float)this.texture.width * this.Scale / 2f, (float)(-(float)this.texture.height) * this.Scale / 2f, 0f);
+ }
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/TextLink.cs b/Client/Assembly-CSharp/TextLink.cs
new file mode 100644
index 0000000..6ad9e25
--- /dev/null
+++ b/Client/Assembly-CSharp/TextLink.cs
@@ -0,0 +1,26 @@
+using System;
+using UnityEngine;
+
+public class TextLink : MonoBehaviour
+{
+ public BoxCollider2D boxCollider;
+
+ public string targetUrl;
+
+ public bool needed;
+
+ public void Set(Vector2 from, Vector2 to, string target)
+ {
+ this.targetUrl = target;
+ Vector2 vector = to + from;
+ base.transform.localPosition = new Vector3(vector.x / 2f, vector.y / 2f, -1f);
+ vector = to - from;
+ vector.y = -vector.y;
+ this.boxCollider.size = vector;
+ }
+
+ public void Click()
+ {
+ Application.OpenURL(this.targetUrl);
+ }
+}
diff --git a/Client/Assembly-CSharp/TextRenderer.cs b/Client/Assembly-CSharp/TextRenderer.cs
new file mode 100644
index 0000000..e0893f1
--- /dev/null
+++ b/Client/Assembly-CSharp/TextRenderer.cs
@@ -0,0 +1,482 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using UnityEngine;
+
+[RequireComponent(typeof(MeshRenderer))]
+[RequireComponent(typeof(MeshFilter))]
+public class TextRenderer : MonoBehaviour
+{
+ public float Width { get; private set; }
+
+ public float Height { get; private set; }
+
+ public Vector3 CursorPos
+ {
+ get
+ {
+ return new Vector3(this.cursorLocation.x / 100f * this.scale, this.cursorLocation.y / 100f * this.scale, -0.001f);
+ }
+ }
+
+ public TextAsset FontData;
+
+ public float scale = 1f;
+
+ public float TabWidth = 0.5f;
+
+ public bool Centered;
+
+ public bool RightAligned;
+
+ public TextLink textLinkPrefab;
+
+ [HideInInspector]
+ private Mesh mesh;
+
+ [HideInInspector]
+ private MeshRenderer render;
+
+ [Multiline]
+ public string Text;
+
+ private string lastText;
+
+ public Color Color = Color.white;
+
+ private Color lastColor = Color.white;
+
+ public Color OutlineColor = Color.black;
+
+ private Color lastOutlineColor = Color.white;
+
+ public float maxWidth = -1f;
+
+ public bool scaleToFit;
+
+ public bool paragraphSpacing;
+
+ private Vector2 cursorLocation;
+
+ public void Start()
+ {
+ this.render = base.GetComponent<MeshRenderer>();
+ MeshFilter component = base.GetComponent<MeshFilter>();
+ if (!component.mesh)
+ {
+ this.mesh = new Mesh();
+ this.mesh.name = "Text" + base.name;
+ component.mesh = this.mesh;
+ this.render.material.SetColor("_OutlineColor", this.OutlineColor);
+ return;
+ }
+ this.mesh = component.mesh;
+ }
+
+ [ContextMenu("Generate Mesh")]
+ public void GenerateMesh()
+ {
+ this.render = base.GetComponent<MeshRenderer>();
+ MeshFilter component = base.GetComponent<MeshFilter>();
+ if (!component.sharedMesh)
+ {
+ this.mesh = new Mesh();
+ this.mesh.name = "Text" + base.name;
+ component.mesh = this.mesh;
+ }
+ else
+ {
+ this.mesh = component.sharedMesh;
+ }
+ this.lastText = null;
+ this.lastOutlineColor = this.OutlineColor;
+ this.Update();
+ }
+
+ private void Update()
+ {
+ if (this.lastOutlineColor != this.OutlineColor)
+ {
+ this.lastOutlineColor = this.OutlineColor;
+ this.render.material.SetColor("_OutlineColor", this.OutlineColor);
+ }
+ if (this.lastText != this.Text || this.lastColor != this.Color)
+ {
+ this.RefreshMesh();
+ }
+ }
+
+ public void RefreshMesh()
+ {
+ if (this.render == null)
+ {
+ this.Start();
+ }
+ if (this.Text != null)
+ {
+ if (this.Text.Any((char c) => c > '✐'))
+ {
+ FontCache.Instance.SetFont(this, "Korean");
+ }
+ }
+ FontData fontData = FontCache.Instance.LoadFont(this.FontData);
+ this.lastText = this.Text;
+ this.lastColor = this.Color;
+ float num = this.scale;
+ if (this.scaleToFit)
+ {
+ num = Mathf.Min(this.scale, this.maxWidth / this.GetMaxWidth(fontData, this.lastText));
+ }
+ else if (this.maxWidth > 0f)
+ {
+ this.lastText = (this.Text = TextRenderer.WrapText(fontData, this.lastText, this.maxWidth));
+ }
+ List<Vector3> list = new List<Vector3>(this.lastText.Length * 4);
+ List<Vector2> list2 = new List<Vector2>(this.lastText.Length * 4);
+ List<Vector4> list3 = new List<Vector4>(this.lastText.Length * 4);
+ List<Color> list4 = new List<Color>(this.lastText.Length * 4);
+ int[] array = new int[this.lastText.Length * 6];
+ this.Width = 0f;
+ this.cursorLocation.x = (this.cursorLocation.y = 0f);
+ int num2 = -1;
+ Vector2 from = default(Vector2);
+ string text = null;
+ int lineStart = 0;
+ int num3 = 0;
+ Color item = this.Color;
+ int? num4 = null;
+ int i = 0;
+ while (i < this.lastText.Length)
+ {
+ int num5 = (int)this.lastText[i];
+ if (num5 == 91)
+ {
+ if (num2 != 91)
+ {
+ if (this.lastText[i + 1] == '[')
+ {
+ goto IL_422;
+ }
+ num4 = new int?(0);
+ num2 = num5;
+ }
+ }
+ else
+ {
+ if (num4 == null)
+ {
+ goto IL_422;
+ }
+ if (num5 == 93)
+ {
+ if (num2 != 91)
+ {
+ int? num6 = num4;
+ byte r = (byte)((num6 != null) ? new int?(num6.GetValueOrDefault() >> 24 & 255) : null).Value;
+ int? num7 = num4;
+ byte g = (byte)((num7 != null) ? new int?(num7.GetValueOrDefault() >> 16 & 255) : null).Value;
+ int? num8 = num4;
+ item = new Color32(r, g, (byte)((num8 != null) ? new int?(num8.GetValueOrDefault() >> 8 & 255) : null).Value, (byte)(num4 & 255).Value);
+ item.a *= this.Color.a;
+ }
+ else
+ {
+ item = this.Color;
+ }
+ num4 = null;
+ if (text != null)
+ {
+ TextLink textLink = UnityEngine.Object.Instantiate<TextLink>(this.textLinkPrefab, base.transform);
+ textLink.transform.localScale = Vector3.one;
+ Vector3 v = list.Last<Vector3>();
+ textLink.Set(from, v, text);
+ text = null;
+ }
+ }
+ else if (num5 == 104)
+ {
+ int num9 = this.lastText.IndexOf(']', i);
+ text = this.lastText.Substring(i, num9 - i);
+ from = list[list.Count - 2];
+ item = new Color(0.5f, 0.5f, 1f);
+ num4 = null;
+ i = num9;
+ }
+ else
+ {
+ num4 = (num4 << 4 | this.CharToInt(num5));
+ }
+ num2 = num5;
+ }
+ IL_81F:
+ i++;
+ continue;
+ IL_422:
+ if (num5 == 13)
+ {
+ goto IL_81F;
+ }
+ if (num5 == 10)
+ {
+ if (this.Centered)
+ {
+ this.CenterVerts(list, this.cursorLocation.x, lineStart, num);
+ }
+ else if (this.RightAligned)
+ {
+ this.RightAlignVerts(list, this.cursorLocation.x, lineStart, num);
+ }
+ bool flag = this.cursorLocation.x == 0f;
+ this.cursorLocation.x = 0f;
+ if (flag)
+ {
+ this.cursorLocation.y = this.cursorLocation.y - fontData.LineHeight / 2f;
+ }
+ else
+ {
+ this.cursorLocation.y = this.cursorLocation.y - fontData.LineHeight;
+ }
+ lineStart = list.Count;
+ goto IL_81F;
+ }
+ if (num5 == 9)
+ {
+ float num10 = this.cursorLocation.x / 100f;
+ num10 = Mathf.Ceil(num10 / this.TabWidth) * this.TabWidth;
+ this.cursorLocation.x = num10 * 100f;
+ goto IL_81F;
+ }
+ int index;
+ if (!fontData.charMap.TryGetValue(num5, out index))
+ {
+ Debug.Log("Missing char :" + num5);
+ num5 = -1;
+ index = fontData.charMap[-1];
+ }
+ Vector4 vector = fontData.bounds[index];
+ Vector2 textureSize = fontData.TextureSize;
+ Vector3 vector2 = fontData.offsets[index];
+ float kerning = fontData.GetKerning(num2, num5);
+ float num11 = this.cursorLocation.x + vector2.x + kerning;
+ float num12 = this.cursorLocation.y - vector2.y;
+ list.Add(new Vector3(num11, num12 - vector.w) / 100f * num);
+ list.Add(new Vector3(num11, num12) / 100f * num);
+ list.Add(new Vector3(num11 + vector.z, num12) / 100f * num);
+ list.Add(new Vector3(num11 + vector.z, num12 - vector.w) / 100f * num);
+ list4.Add(item);
+ list4.Add(item);
+ list4.Add(item);
+ list4.Add(item);
+ list2.Add(new Vector2(vector.x / textureSize.x, 1f - (vector.y + vector.w) / textureSize.y));
+ list2.Add(new Vector2(vector.x / textureSize.x, 1f - vector.y / textureSize.y));
+ list2.Add(new Vector2((vector.x + vector.z) / textureSize.x, 1f - vector.y / textureSize.y));
+ list2.Add(new Vector2((vector.x + vector.z) / textureSize.x, 1f - (vector.y + vector.w) / textureSize.y));
+ Vector4 item2 = fontData.Channels[index];
+ list3.Add(item2);
+ list3.Add(item2);
+ list3.Add(item2);
+ list3.Add(item2);
+ array[num3 * 6] = num3 * 4;
+ array[num3 * 6 + 1] = num3 * 4 + 1;
+ array[num3 * 6 + 2] = num3 * 4 + 2;
+ array[num3 * 6 + 3] = num3 * 4;
+ array[num3 * 6 + 4] = num3 * 4 + 2;
+ array[num3 * 6 + 5] = num3 * 4 + 3;
+ this.cursorLocation.x = this.cursorLocation.x + (vector2.z + kerning);
+ float num13 = this.cursorLocation.x / 100f * num;
+ if (this.Width < num13)
+ {
+ this.Width = num13;
+ }
+ num2 = num5;
+ num3++;
+ goto IL_81F;
+ }
+ if (this.Centered)
+ {
+ this.CenterVerts(list, this.cursorLocation.x, lineStart, num);
+ this.cursorLocation.x = this.cursorLocation.x / 2f;
+ this.Width /= 2f;
+ }
+ else if (this.RightAligned)
+ {
+ this.RightAlignVerts(list, this.cursorLocation.x, lineStart, num);
+ }
+ this.Height = -(this.cursorLocation.y - fontData.LineHeight) / 100f * num;
+ this.mesh.Clear();
+ if (list.Count > 0)
+ {
+ this.mesh.SetVertices(list);
+ this.mesh.SetColors(list4);
+ this.mesh.SetUVs(0, list2);
+ this.mesh.SetUVs(1, list3);
+ this.mesh.SetIndices(array, MeshTopology.Triangles, 0);
+ }
+ }
+
+ private float GetMaxWidth(FontData data, string lastText)
+ {
+ float num = 0f;
+ float num2 = 0f;
+ int last = -1;
+ bool flag = false;
+ int num3 = 0;
+ int num4 = 0;
+ while (num4 < lastText.Length && num3++ <= 1000)
+ {
+ int num5 = (int)lastText[num4];
+ if (num5 == 91)
+ {
+ flag = true;
+ goto IL_4D;
+ }
+ if (num5 != 93)
+ {
+ goto IL_4D;
+ }
+ flag = false;
+ IL_100:
+ num4++;
+ continue;
+ IL_4D:
+ if (flag || num5 == 13)
+ {
+ goto IL_100;
+ }
+ if (num5 == 10)
+ {
+ last = -1;
+ num2 = 0f;
+ goto IL_100;
+ }
+ if (num5 == 9)
+ {
+ num2 = Mathf.Ceil(num2 / 100f / 0.5f) * 0.5f * 100f;
+ goto IL_100;
+ }
+ int index;
+ if (!data.charMap.TryGetValue(num5, out index))
+ {
+ Debug.Log("Missing char :" + num5);
+ num5 = -1;
+ index = data.charMap[-1];
+ }
+ Vector3 vector = data.offsets[index];
+ num2 += vector.z + data.GetKerning(last, num5);
+ if (num2 > num)
+ {
+ num = num2;
+ }
+ last = num5;
+ goto IL_100;
+ }
+ return num / 100f;
+ }
+
+ private void RightAlignVerts(List<Vector3> verts, float baseX, int lineStart, float scale)
+ {
+ for (int i = lineStart; i < verts.Count; i++)
+ {
+ Vector3 value = verts[i];
+ value.x -= baseX / 100f * scale;
+ verts[i] = value;
+ }
+ }
+
+ private void CenterVerts(List<Vector3> verts, float baseX, int lineStart, float scale)
+ {
+ for (int i = lineStart; i < verts.Count; i++)
+ {
+ Vector3 value = verts[i];
+ value.x -= baseX / 200f * scale;
+ verts[i] = value;
+ }
+ }
+
+ private int CharToInt(int c)
+ {
+ if (c < 65)
+ {
+ return c - 48;
+ }
+ if (c < 97)
+ {
+ return 10 + (c - 65);
+ }
+ return 10 + (c - 97);
+ }
+
+ public static string WrapText(FontData data, string displayTxt, float maxWidth)
+ {
+ float num = 0f;
+ int num2 = -1;
+ int last = -1;
+ bool flag = false;
+ int num3 = 0;
+ int num4 = 0;
+ while (num4 < displayTxt.Length && num3++ <= 1000)
+ {
+ int num5 = (int)displayTxt[num4];
+ if (num5 == 91)
+ {
+ flag = true;
+ goto IL_49;
+ }
+ if (num5 != 93)
+ {
+ goto IL_49;
+ }
+ flag = false;
+ IL_155:
+ num4++;
+ continue;
+ IL_49:
+ if (flag || num5 == 13)
+ {
+ goto IL_155;
+ }
+ if (num5 == 10)
+ {
+ num2 = -1;
+ last = -1;
+ num = 0f;
+ goto IL_155;
+ }
+ if (num5 == 9)
+ {
+ num = Mathf.Ceil(num / 100f / 0.5f) * 0.5f * 100f;
+ goto IL_155;
+ }
+ int index;
+ if (!data.charMap.TryGetValue(num5, out index))
+ {
+ Debug.Log("Missing char :" + num5);
+ num5 = -1;
+ index = data.charMap[-1];
+ }
+ if (num5 == 32)
+ {
+ num2 = num4;
+ }
+ Vector3 vector = data.offsets[index];
+ num += vector.z + data.GetKerning(last, num5);
+ if (num > maxWidth * 100f)
+ {
+ if (num2 != -1)
+ {
+ displayTxt = displayTxt.Substring(0, num2) + "\n" + displayTxt.Substring(num2 + 1);
+ num4 = num2;
+ }
+ else
+ {
+ displayTxt = displayTxt.Substring(0, num4) + "\n" + displayTxt.Substring(num4);
+ }
+ num2 = -1;
+ num = 0f;
+ }
+ last = num5;
+ goto IL_155;
+ }
+ return displayTxt;
+ }
+}
diff --git a/Client/Assembly-CSharp/TextTranslator.cs b/Client/Assembly-CSharp/TextTranslator.cs
new file mode 100644
index 0000000..bb51e1b
--- /dev/null
+++ b/Client/Assembly-CSharp/TextTranslator.cs
@@ -0,0 +1,24 @@
+using System;
+using UnityEngine;
+
+[RequireComponent(typeof(TextRenderer))]
+public class TextTranslator : MonoBehaviour, ITranslatedText
+{
+ public StringNames TargetText;
+
+ public void ResetText()
+ {
+ base.GetComponent<TextRenderer>().Text = DestroyableSingleton<TranslationController>.Instance.GetString(this.TargetText, Array.Empty<object>());
+ }
+
+ public void Start()
+ {
+ DestroyableSingleton<TranslationController>.Instance.ActiveTexts.Add(this);
+ this.ResetText();
+ }
+
+ public void OnDestroy()
+ {
+ DestroyableSingleton<TranslationController>.Instance.ActiveTexts.Remove(this);
+ }
+}
diff --git a/Client/Assembly-CSharp/ToggleButtonBehaviour.cs b/Client/Assembly-CSharp/ToggleButtonBehaviour.cs
new file mode 100644
index 0000000..4703e3e
--- /dev/null
+++ b/Client/Assembly-CSharp/ToggleButtonBehaviour.cs
@@ -0,0 +1,42 @@
+using System;
+using UnityEngine;
+
+public class ToggleButtonBehaviour : MonoBehaviour, ITranslatedText
+{
+ public StringNames BaseText;
+
+ public TextRenderer Text;
+
+ public SpriteRenderer Background;
+
+ public ButtonRolloverHandler Rollover;
+
+ private bool onState;
+
+ public void Start()
+ {
+ DestroyableSingleton<TranslationController>.Instance.ActiveTexts.Add(this);
+ }
+
+ public void OnDestroy()
+ {
+ DestroyableSingleton<TranslationController>.Instance.ActiveTexts.Remove(this);
+ }
+
+ public void ResetText()
+ {
+ this.Text.Text = DestroyableSingleton<TranslationController>.Instance.GetString(this.BaseText, Array.Empty<object>()) + ": " + DestroyableSingleton<TranslationController>.Instance.GetString(this.onState ? StringNames.SettingsOn : StringNames.SettingsOff, Array.Empty<object>());
+ }
+
+ public void UpdateText(bool on)
+ {
+ this.onState = on;
+ Color color = on ? new Color(0f, 1f, 0.16470589f, 1f) : Color.white;
+ this.Background.color = color;
+ this.ResetText();
+ if (this.Rollover)
+ {
+ this.Rollover.OutColor = color;
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/ToggleOption.cs b/Client/Assembly-CSharp/ToggleOption.cs
new file mode 100644
index 0000000..25ffbe7
--- /dev/null
+++ b/Client/Assembly-CSharp/ToggleOption.cs
@@ -0,0 +1,45 @@
+using System;
+using UnityEngine;
+
+public class ToggleOption : OptionBehaviour
+{
+ public TextRenderer TitleText;
+
+ public SpriteRenderer CheckMark;
+
+ private bool oldValue;
+
+ public void OnEnable()
+ {
+ this.TitleText.Text = DestroyableSingleton<TranslationController>.Instance.GetString(this.Title, Array.Empty<object>());
+ GameOptionsData gameOptions = PlayerControl.GameOptions;
+ StringNames title = this.Title;
+ if (title == StringNames.GameRecommendedSettings)
+ {
+ this.CheckMark.enabled = gameOptions.isDefaults;
+ return;
+ }
+ Debug.Log("Ono, unrecognized setting: " + this.Title);
+ }
+
+ private void FixedUpdate()
+ {
+ bool @bool = this.GetBool();
+ if (this.oldValue != @bool)
+ {
+ this.oldValue = @bool;
+ this.CheckMark.enabled = @bool;
+ }
+ }
+
+ public void Toggle()
+ {
+ this.CheckMark.enabled = !this.CheckMark.enabled;
+ this.OnValueChanged(this);
+ }
+
+ public override bool GetBool()
+ {
+ return this.CheckMark.enabled;
+ }
+}
diff --git a/Client/Assembly-CSharp/TowerBehaviour.cs b/Client/Assembly-CSharp/TowerBehaviour.cs
new file mode 100644
index 0000000..dbf85b2
--- /dev/null
+++ b/Client/Assembly-CSharp/TowerBehaviour.cs
@@ -0,0 +1,43 @@
+using System;
+using UnityEngine;
+
+public class TowerBehaviour : MonoBehaviour
+{
+ public float timer;
+
+ public float frameTime = 0.2f;
+
+ public SpriteRenderer circle;
+
+ public SpriteRenderer middle1;
+
+ public SpriteRenderer middle2;
+
+ public SpriteRenderer outer1;
+
+ public SpriteRenderer outer2;
+
+ public void Update()
+ {
+ this.timer += Time.deltaTime;
+ if (this.timer < this.frameTime)
+ {
+ this.circle.color = Color.white;
+ this.middle1.color = (this.middle2.color = (this.outer1.color = (this.outer2.color = Color.black)));
+ return;
+ }
+ if (this.timer < 2f * this.frameTime)
+ {
+ this.middle1.color = (this.middle2.color = Color.white);
+ this.circle.color = (this.outer1.color = (this.outer2.color = Color.black));
+ return;
+ }
+ if (this.timer < 3f * this.frameTime)
+ {
+ this.outer1.color = (this.outer2.color = Color.white);
+ this.middle1.color = (this.middle2.color = (this.circle.color = Color.black));
+ return;
+ }
+ this.timer = 0f;
+ }
+}
diff --git a/Client/Assembly-CSharp/TransitionOpen.cs b/Client/Assembly-CSharp/TransitionOpen.cs
new file mode 100644
index 0000000..b846e44
--- /dev/null
+++ b/Client/Assembly-CSharp/TransitionOpen.cs
@@ -0,0 +1,54 @@
+using System;
+using System.Collections;
+using UnityEngine;
+using UnityEngine.UI;
+
+public class TransitionOpen : MonoBehaviour
+{
+ public float duration = 0.2f;
+
+ public Button.ButtonClickedEvent OnClose = new Button.ButtonClickedEvent();
+
+ public void OnEnable()
+ {
+ base.StartCoroutine(this.AnimateOpen());
+ }
+
+ public void Close()
+ {
+ base.StartCoroutine(this.AnimateClose());
+ }
+
+ private IEnumerator AnimateClose()
+ {
+ Vector3 vec = default(Vector3);
+ for (float t = 0f; t < this.duration; t += Time.deltaTime)
+ {
+ float t2 = t / this.duration;
+ float num = Mathf.SmoothStep(1f, 0f, t2);
+ vec.Set(num, num, num);
+ base.transform.localScale = vec;
+ yield return null;
+ }
+ vec.Set(0f, 0f, 0f);
+ base.transform.localScale = vec;
+ this.OnClose.Invoke();
+ yield break;
+ }
+
+ private IEnumerator AnimateOpen()
+ {
+ Vector3 vec = default(Vector3);
+ for (float t = 0f; t < this.duration; t += Time.deltaTime)
+ {
+ float t2 = t / this.duration;
+ float num = Mathf.SmoothStep(0f, 1f, t2);
+ vec.Set(num, num, num);
+ base.transform.localScale = vec;
+ yield return null;
+ }
+ vec.Set(1f, 1f, 1f);
+ base.transform.localScale = vec;
+ yield break;
+ }
+}
diff --git a/Client/Assembly-CSharp/TransitionType.cs b/Client/Assembly-CSharp/TransitionType.cs
new file mode 100644
index 0000000..07e5b99
--- /dev/null
+++ b/Client/Assembly-CSharp/TransitionType.cs
@@ -0,0 +1,7 @@
+using System;
+
+public enum TransitionType
+{
+ SlideBottom,
+ Alpha
+}
diff --git a/Client/Assembly-CSharp/TranslatedImageSet.cs b/Client/Assembly-CSharp/TranslatedImageSet.cs
new file mode 100644
index 0000000..2a43583
--- /dev/null
+++ b/Client/Assembly-CSharp/TranslatedImageSet.cs
@@ -0,0 +1,8 @@
+using System;
+using UnityEngine;
+
+[CreateAssetMenu]
+public class TranslatedImageSet : ScriptableObject
+{
+ public ImageData[] Images;
+}
diff --git a/Client/Assembly-CSharp/TranslationController.cs b/Client/Assembly-CSharp/TranslationController.cs
new file mode 100644
index 0000000..66686f7
--- /dev/null
+++ b/Client/Assembly-CSharp/TranslationController.cs
@@ -0,0 +1,70 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using UnityEngine;
+
+public class TranslationController : DestroyableSingleton<TranslationController>
+{
+ private static readonly StringNames[] SystemTypesToStringNames = SystemTypeHelpers.AllTypes.Select(delegate(SystemTypes t)
+ {
+ StringNames result;
+ Enum.TryParse<StringNames>(t.ToString(), out result);
+ return result;
+ }).ToArray<StringNames>();
+
+ private static readonly StringNames[] TaskTypesToStringNames = TaskTypesHelpers.AllTypes.Select(delegate(TaskTypes t)
+ {
+ StringNames result;
+ Enum.TryParse<StringNames>(t.ToString(), out result);
+ return result;
+ }).ToArray<StringNames>();
+
+ public TextAsset[] Languages;
+
+ public TranslatedImageSet[] Images;
+
+ public LanguageUnit CurrentLanguage;
+
+ public List<ITranslatedText> ActiveTexts = new List<ITranslatedText>();
+
+ public override void Awake()
+ {
+ base.Awake();
+ if (DestroyableSingleton<TranslationController>.Instance == this)
+ {
+ this.CurrentLanguage = new LanguageUnit(this.Languages[(int)SaveManager.LastLanguage], this.Images[(int)SaveManager.LastLanguage].Images);
+ }
+ }
+
+ public void SetLanguage(TextAsset lang)
+ {
+ int num = this.Languages.IndexOf(lang);
+ Debug.Log("Set language to " + num);
+ SaveManager.LastLanguage = (uint)num;
+ this.CurrentLanguage = new LanguageUnit(this.Languages[num], this.Images[num].Images);
+ for (int i = 0; i < this.ActiveTexts.Count; i++)
+ {
+ this.ActiveTexts[i].ResetText();
+ }
+ }
+
+ public Sprite GetImage(ImageNames id)
+ {
+ return this.CurrentLanguage.GetImage(id);
+ }
+
+ public string GetString(StringNames id, params object[] parts)
+ {
+ return this.CurrentLanguage.GetString(id, parts);
+ }
+
+ public string GetString(SystemTypes room)
+ {
+ return this.GetString(TranslationController.SystemTypesToStringNames[(int)room], Array.Empty<object>());
+ }
+
+ public string GetString(TaskTypes task)
+ {
+ return this.GetString(TranslationController.TaskTypesToStringNames[(int)((byte)task)], Array.Empty<object>());
+ }
+}
diff --git a/Client/Assembly-CSharp/TumbleBoxBehaviour.cs b/Client/Assembly-CSharp/TumbleBoxBehaviour.cs
new file mode 100644
index 0000000..8d9f722
--- /dev/null
+++ b/Client/Assembly-CSharp/TumbleBoxBehaviour.cs
@@ -0,0 +1,24 @@
+using System;
+using UnityEngine;
+
+public class TumbleBoxBehaviour : MonoBehaviour
+{
+ public FloatRange BoxHeight;
+
+ public FloatRange shadowScale;
+
+ public SpriteRenderer Shadow;
+
+ public SpriteRenderer Box;
+
+ public void FixedUpdate()
+ {
+ float z = Time.time * 15f;
+ float v = Mathf.Cos(Time.time * 3.1415927f / 10f) / 2f + 0.5f;
+ float num = this.shadowScale.Lerp(v);
+ this.Shadow.transform.localScale = new Vector3(num, num, num);
+ float y = this.BoxHeight.Lerp(v);
+ this.Box.transform.localPosition = new Vector3(0f, y, -0.01f);
+ this.Box.transform.eulerAngles = new Vector3(0f, 0f, z);
+ }
+}
diff --git a/Client/Assembly-CSharp/TuneRadioMinigame.cs b/Client/Assembly-CSharp/TuneRadioMinigame.cs
new file mode 100644
index 0000000..ac2eb58
--- /dev/null
+++ b/Client/Assembly-CSharp/TuneRadioMinigame.cs
@@ -0,0 +1,104 @@
+using System;
+using UnityEngine;
+
+public class TuneRadioMinigame : Minigame
+{
+ public RadioWaveBehaviour actualSignal;
+
+ public DialBehaviour dial;
+
+ public SpriteRenderer redLight;
+
+ public SpriteRenderer greenLight;
+
+ public float Tolerance = 0.1f;
+
+ public float targetAngle;
+
+ public bool finished;
+
+ private float steadyTimer;
+
+ public AudioClip StaticSound;
+
+ public AudioClip RadioSound;
+
+ public override void Begin(PlayerTask task)
+ {
+ base.Begin(task);
+ this.targetAngle = this.dial.DialRange.Next();
+ if (Constants.ShouldPlaySfx())
+ {
+ SoundManager.Instance.PlayDynamicSound("CommsRadio", this.RadioSound, true, new DynamicSound.GetDynamicsFunction(this.GetRadioVolume), true);
+ SoundManager.Instance.PlayDynamicSound("RadioStatic", this.StaticSound, true, new DynamicSound.GetDynamicsFunction(this.GetStaticVolume), true);
+ }
+ }
+
+ private void GetRadioVolume(AudioSource player, float dt)
+ {
+ player.volume = 1f - this.actualSignal.NoiseLevel;
+ }
+
+ private void GetStaticVolume(AudioSource player, float dt)
+ {
+ player.volume = this.actualSignal.NoiseLevel;
+ }
+
+ public void Update()
+ {
+ if (this.finished)
+ {
+ return;
+ }
+ float f = Mathf.Abs((this.targetAngle - this.dial.Value) / this.dial.DialRange.Width) * 2f;
+ this.actualSignal.NoiseLevel = Mathf.Clamp(Mathf.Sqrt(f), 0f, 1f);
+ if (this.actualSignal.NoiseLevel <= this.Tolerance)
+ {
+ this.redLight.color = new Color(0.35f, 0f, 0f);
+ if (!this.dial.Engaged)
+ {
+ this.FinishGame();
+ return;
+ }
+ this.steadyTimer += Time.deltaTime;
+ if (this.steadyTimer > 1.5f)
+ {
+ this.FinishGame();
+ return;
+ }
+ }
+ else
+ {
+ this.redLight.color = new Color(1f, 0f, 0f);
+ this.steadyTimer = 0f;
+ }
+ }
+
+ private void FinishGame()
+ {
+ this.greenLight.color = Color.green;
+ this.finished = true;
+ this.dial.enabled = false;
+ this.dial.SetValue(this.targetAngle);
+ this.actualSignal.NoiseLevel = 0f;
+ if (PlayerControl.LocalPlayer)
+ {
+ ShipStatus.Instance.RpcRepairSystem(SystemTypes.Comms, 0);
+ }
+ base.StartCoroutine(base.CoStartClose(0.75f));
+ try
+ {
+ ((SabotageTask)this.MyTask).MarkContributed();
+ }
+ catch
+ {
+ }
+ }
+
+ public override void Close()
+ {
+ SoundManager.Instance.StopSound(this.StaticSound);
+ SoundManager.Instance.StopSound(this.RadioSound);
+ base.Close();
+ }
+}
diff --git a/Client/Assembly-CSharp/TutorialManager.cs b/Client/Assembly-CSharp/TutorialManager.cs
new file mode 100644
index 0000000..ba89235
--- /dev/null
+++ b/Client/Assembly-CSharp/TutorialManager.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Collections;
+using InnerNet;
+using UnityEngine;
+
+public class TutorialManager : DestroyableSingleton<TutorialManager>
+{
+ public PlayerControl PlayerPrefab;
+
+ public Transform[] DummyLocations;
+
+ public override void Awake()
+ {
+ base.Awake();
+ StatsManager.Instance = new TutorialStatsManager();
+ base.StartCoroutine(this.RunTutorial());
+ }
+
+ public override void OnDestroy()
+ {
+ StatsManager.Instance = new StatsManager();
+ base.OnDestroy();
+ }
+
+ private IEnumerator RunTutorial()
+ {
+ while (!ShipStatus.Instance)
+ {
+ yield return null;
+ }
+ ShipStatus.Instance.enabled = false;
+ ShipStatus.Instance.Timer = 15f;
+ while (!PlayerControl.LocalPlayer)
+ {
+ yield return null;
+ }
+ if (DestroyableSingleton<DiscordManager>.InstanceExists)
+ {
+ DestroyableSingleton<DiscordManager>.Instance.SetHowToPlay();
+ }
+ PlayerControl.GameOptions = new GameOptionsData
+ {
+ NumImpostors = 0,
+ DiscussionTime = 0
+ };
+ PlayerControl.LocalPlayer.RpcSetInfected(new GameData.PlayerInfo[0]);
+ for (int i = 0; i < this.DummyLocations.Length; i++)
+ {
+ PlayerControl playerControl = UnityEngine.Object.Instantiate<PlayerControl>(this.PlayerPrefab);
+ playerControl.PlayerId = (byte)GameData.Instance.GetAvailableId();
+ GameData.Instance.AddPlayer(playerControl);
+ AmongUsClient.Instance.Spawn(playerControl, -2, SpawnFlags.None);
+ playerControl.transform.position = this.DummyLocations[i].position;
+ playerControl.GetComponent<DummyBehaviour>().enabled = true;
+ playerControl.NetTransform.enabled = false;
+ playerControl.SetName("Dummy " + (i + 1));
+ playerControl.SetColor((byte)((i < (int)SaveManager.BodyColor) ? i : (i + 1)));
+ GameData.Instance.RpcSetTasks(playerControl.PlayerId, new byte[0]);
+ }
+ ShipStatus.Instance.Begin();
+ yield break;
+ }
+}
diff --git a/Client/Assembly-CSharp/TutorialStatsManager.cs b/Client/Assembly-CSharp/TutorialStatsManager.cs
new file mode 100644
index 0000000..6d473ed
--- /dev/null
+++ b/Client/Assembly-CSharp/TutorialStatsManager.cs
@@ -0,0 +1,12 @@
+using System;
+
+public class TutorialStatsManager : StatsManager
+{
+ protected override void LoadStats()
+ {
+ }
+
+ protected override void SaveStats()
+ {
+ }
+}
diff --git a/Client/Assembly-CSharp/TwitterLink.cs b/Client/Assembly-CSharp/TwitterLink.cs
new file mode 100644
index 0000000..816c0fb
--- /dev/null
+++ b/Client/Assembly-CSharp/TwitterLink.cs
@@ -0,0 +1,12 @@
+using System;
+using UnityEngine;
+
+public class TwitterLink : MonoBehaviour
+{
+ public string LinkUrl = "https://www.twitter.com/InnerslothDevs";
+
+ public void Click()
+ {
+ Application.OpenURL(this.LinkUrl);
+ }
+}
diff --git a/Client/Assembly-CSharp/UnlockManifoldsMinigame.cs b/Client/Assembly-CSharp/UnlockManifoldsMinigame.cs
new file mode 100644
index 0000000..16f6269
--- /dev/null
+++ b/Client/Assembly-CSharp/UnlockManifoldsMinigame.cs
@@ -0,0 +1,100 @@
+using System;
+using System.Collections;
+using System.Linq;
+using UnityEngine;
+
+public class UnlockManifoldsMinigame : Minigame
+{
+ public SpriteRenderer[] Buttons;
+
+ public byte SystemId;
+
+ private int buttonCounter;
+
+ private bool animating;
+
+ public AudioClip PressButtonSound;
+
+ public AudioClip FailSound;
+
+ public override void Begin(PlayerTask task)
+ {
+ base.Begin(task);
+ int num = 2;
+ int num2 = this.Buttons.Length / num;
+ float[] array = FloatRange.SpreadToEdges(-1.7f, 1.7f, num2).ToArray<float>();
+ float[] array2 = FloatRange.SpreadToEdges(-0.43f, 0.43f, num).ToArray<float>();
+ SpriteRenderer[] array3 = this.Buttons.ToArray<SpriteRenderer>();
+ array3.Shuffle<SpriteRenderer>();
+ for (int i = 0; i < num2; i++)
+ {
+ for (int j = 0; j < num; j++)
+ {
+ int num3 = i + j * num2;
+ array3[num3].transform.localPosition = new Vector3(array[i], array2[j], 0f);
+ }
+ }
+ }
+
+ public void HitButton(int idx)
+ {
+ if (this.MyNormTask.IsComplete)
+ {
+ return;
+ }
+ if (this.animating)
+ {
+ return;
+ }
+ if (Constants.ShouldPlaySfx())
+ {
+ SoundManager.Instance.PlaySound(this.PressButtonSound, false, 1f).pitch = Mathf.Lerp(0.5f, 1.5f, (float)idx / 10f);
+ }
+ if (idx == this.buttonCounter)
+ {
+ this.Buttons[idx].color = Color.green;
+ this.buttonCounter++;
+ if (this.buttonCounter == this.Buttons.Length)
+ {
+ this.MyNormTask.NextStep();
+ base.StartCoroutine(base.CoStartClose(0.75f));
+ return;
+ }
+ }
+ else
+ {
+ this.buttonCounter = 0;
+ base.StartCoroutine(this.ResetAll());
+ }
+ }
+
+ private IEnumerator ResetAll()
+ {
+ if (Constants.ShouldPlaySfx())
+ {
+ SoundManager.Instance.PlaySound(this.FailSound, false, 1f);
+ }
+ this.animating = true;
+ for (int i = 0; i < this.Buttons.Length; i++)
+ {
+ this.Buttons[i].color = Color.red;
+ }
+ yield return new WaitForSeconds(0.25f);
+ for (int j = 0; j < this.Buttons.Length; j++)
+ {
+ this.Buttons[j].color = Color.white;
+ }
+ yield return new WaitForSeconds(0.25f);
+ for (int k = 0; k < this.Buttons.Length; k++)
+ {
+ this.Buttons[k].color = Color.red;
+ }
+ yield return new WaitForSeconds(0.25f);
+ for (int l = 0; l < this.Buttons.Length; l++)
+ {
+ this.Buttons[l].color = Color.white;
+ }
+ this.animating = false;
+ yield break;
+ }
+}
diff --git a/Client/Assembly-CSharp/UnlockPopUp.cs b/Client/Assembly-CSharp/UnlockPopUp.cs
new file mode 100644
index 0000000..22675fa
--- /dev/null
+++ b/Client/Assembly-CSharp/UnlockPopUp.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections;
+using UnityEngine;
+
+public class UnlockPopUp : MonoBehaviour
+{
+ public IEnumerator Show()
+ {
+ DateTime utcNow = DateTime.UtcNow;
+ if ((utcNow.DayOfYear < 350 && utcNow.DayOfYear > 4) || SaveManager.GetPurchase("hats_newyears2018"))
+ {
+ yield break;
+ }
+ base.gameObject.SetActive(true);
+ SaveManager.SetPurchased("hats_newyears2018");
+ while (base.isActiveAndEnabled)
+ {
+ yield return null;
+ }
+ yield break;
+ }
+}
diff --git a/Client/Assembly-CSharp/UploadDataGame.cs b/Client/Assembly-CSharp/UploadDataGame.cs
new file mode 100644
index 0000000..0f3d95c
--- /dev/null
+++ b/Client/Assembly-CSharp/UploadDataGame.cs
@@ -0,0 +1,203 @@
+using System;
+using System.Collections;
+using System.Text;
+using PowerTools;
+using UnityEngine;
+
+public class UploadDataGame : Minigame
+{
+ public SpriteAnim LeftFolder;
+
+ public SpriteAnim RightFolder;
+
+ public AnimationClip FolderOpen;
+
+ public AnimationClip FolderClose;
+
+ public SpriteRenderer Runner;
+
+ public HorizontalGauge Gauge;
+
+ public TextRenderer PercentText;
+
+ public TextRenderer EstimatedText;
+
+ public TextRenderer SourceText;
+
+ public TextRenderer TargetText;
+
+ public SpriteRenderer Button;
+
+ public Sprite DownloadImage;
+
+ public GameObject Status;
+
+ public GameObject Tower;
+
+ private int count;
+
+ private float timer;
+
+ public const float RandomChunks = 5f;
+
+ public const float ConstantTime = 3f;
+
+ private bool running = true;
+
+ public override void Begin(PlayerTask task)
+ {
+ PlayerControl.LocalPlayer.SetPlayerMaterialColors(this.Runner);
+ base.Begin(task);
+ if (this.MyNormTask.taskStep == 0)
+ {
+ this.Button.sprite = this.DownloadImage;
+ this.Tower.SetActive(false);
+ this.SourceText.Text = this.MyTask.StartAt.ToString();
+ this.TargetText.Text = "My Tablet";
+ return;
+ }
+ this.SourceText.Text = "My Tablet";
+ this.TargetText.Text = "Headquarters";
+ }
+
+ public void Click()
+ {
+ base.StartCoroutine(this.Transition());
+ }
+
+ private IEnumerator Transition()
+ {
+ this.Button.gameObject.SetActive(false);
+ this.Status.SetActive(true);
+ float target = this.Gauge.transform.localScale.x;
+ for (float t = 0f; t < 0.15f; t += Time.deltaTime)
+ {
+ this.Gauge.transform.localScale = new Vector3(t / 0.15f * target, 1f, 1f);
+ yield return null;
+ }
+ base.StartCoroutine(this.PulseText());
+ base.StartCoroutine(this.DoRun());
+ base.StartCoroutine(this.DoText());
+ base.StartCoroutine(this.DoPercent());
+ yield break;
+ }
+
+ private IEnumerator PulseText()
+ {
+ MeshRenderer rend2 = this.PercentText.GetComponent<MeshRenderer>();
+ MeshRenderer rend1 = this.EstimatedText.GetComponent<MeshRenderer>();
+ Color gray = new Color(0.3f, 0.3f, 0.3f, 1f);
+ while (this.running)
+ {
+ yield return new WaitForLerp(0.4f, delegate(float t)
+ {
+ Color value = Color.Lerp(Color.black, gray, t);
+ rend2.material.SetColor("_OutlineColor", value);
+ rend1.material.SetColor("_OutlineColor", value);
+ });
+ yield return new WaitForLerp(0.4f, delegate(float t)
+ {
+ Color value = Color.Lerp(gray, Color.black, t);
+ rend2.material.SetColor("_OutlineColor", value);
+ rend1.material.SetColor("_OutlineColor", value);
+ });
+ }
+ rend2.material.SetColor("_OutlineColor", Color.black);
+ rend1.material.SetColor("_OutlineColor", Color.black);
+ yield break;
+ }
+
+ private IEnumerator DoPercent()
+ {
+ while (this.running)
+ {
+ float num = (float)this.count / 5f * 0.7f + this.timer / 3f * 0.3f;
+ if (num >= 1f)
+ {
+ this.running = false;
+ }
+ num = Mathf.Clamp(num, 0f, 1f);
+ this.Gauge.Value = num;
+ this.PercentText.Text = Mathf.RoundToInt(num * 100f) + "%";
+ yield return null;
+ }
+ yield break;
+ }
+
+ private IEnumerator DoText()
+ {
+ StringBuilder txt = new StringBuilder("Estimated Time: ");
+ int baselen = txt.Length;
+ int max = 604800;
+ this.count = 0;
+ while ((float)this.count < 5f)
+ {
+ txt.Length = baselen;
+ int num = IntRange.Next(max / 6, max);
+ int num2 = num / 86400;
+ if (num2 > 0)
+ {
+ txt.Append(num2 + "d ");
+ }
+ int num3 = num / 3600 % 24;
+ if (num3 > 0)
+ {
+ txt.Append(num3 + "hr ");
+ }
+ int num4 = num / 60 % 60;
+ if (num4 > 0)
+ {
+ txt.Append(num4 + "m ");
+ }
+ int num5 = num % 60;
+ if (num5 > 0)
+ {
+ txt.Append(num5 + "s");
+ }
+ this.EstimatedText.Text = txt.ToString();
+ max /= 4;
+ yield return new WaitForSeconds(FloatRange.Next(0.6f, 1.2f));
+ this.count++;
+ }
+ this.timer = 0f;
+ while (this.timer < 3f)
+ {
+ txt.Length = baselen;
+ int num6 = Mathf.RoundToInt(3f - this.timer);
+ txt.Append(num6 + "s");
+ this.EstimatedText.Text = txt.ToString();
+ yield return null;
+ this.timer += Time.deltaTime;
+ }
+ yield break;
+ }
+
+ private IEnumerator DoRun()
+ {
+ while (this.running)
+ {
+ UploadDataGame.<>c__DisplayClass25_0 CS$<>8__locals1 = new UploadDataGame.<>c__DisplayClass25_0();
+ CS$<>8__locals1.<>4__this = this;
+ this.LeftFolder.Play(this.FolderOpen, 1f);
+ CS$<>8__locals1.pos = this.Runner.transform.localPosition;
+ yield return new WaitForLerp(1.125f, delegate(float t)
+ {
+ CS$<>8__locals1.pos.x = Mathf.Lerp(-1.25f, 0.5625f, t);
+ CS$<>8__locals1.<>4__this.Runner.transform.localPosition = CS$<>8__locals1.pos;
+ });
+ this.LeftFolder.Play(this.FolderClose, 1f);
+ this.RightFolder.Play(this.FolderOpen, 1f);
+ yield return new WaitForLerp(1.375f, delegate(float t)
+ {
+ CS$<>8__locals1.pos.x = Mathf.Lerp(0.5625f, 1.25f, t);
+ CS$<>8__locals1.<>4__this.Runner.transform.localPosition = CS$<>8__locals1.pos;
+ });
+ yield return new WaitForAnimationFinish(this.RightFolder, this.FolderClose);
+ CS$<>8__locals1 = null;
+ }
+ this.EstimatedText.Text = "Complete";
+ this.MyNormTask.NextStep();
+ base.StartCoroutine(base.CoStartClose(0.75f));
+ yield break;
+ }
+}
diff --git a/Client/Assembly-CSharp/UploadDataTask.cs b/Client/Assembly-CSharp/UploadDataTask.cs
new file mode 100644
index 0000000..8d4aafa
--- /dev/null
+++ b/Client/Assembly-CSharp/UploadDataTask.cs
@@ -0,0 +1,34 @@
+using System;
+using System.Linq;
+using System.Text;
+
+public class UploadDataTask : NormalPlayerTask
+{
+ public override bool ValidConsole(global::Console console)
+ {
+ return (console.Room == this.StartAt && console.ValidTasks.Any((TaskSet set) => this.TaskType == set.taskType && set.taskStep.Contains(this.taskStep))) || (this.taskStep == 1 && console.TaskTypes.Contains(this.TaskType));
+ }
+
+ public override void AppendTaskText(StringBuilder sb)
+ {
+ if (this.taskStep > 0)
+ {
+ if (this.IsComplete)
+ {
+ sb.Append("[00DD00FF]");
+ }
+ else
+ {
+ sb.Append("[FFFF00FF]");
+ }
+ }
+ sb.Append(DestroyableSingleton<TranslationController>.Instance.GetString((this.taskStep == 0) ? this.StartAt : SystemTypes.Admin));
+ sb.Append(": ");
+ sb.Append(DestroyableSingleton<TranslationController>.Instance.GetString((this.taskStep == 0) ? StringNames.DownloadData : StringNames.UploadData, Array.Empty<object>()));
+ sb.Append(" (");
+ sb.Append(this.taskStep);
+ sb.Append("/");
+ sb.Append(this.MaxStep);
+ sb.AppendLine(") []");
+ }
+}
diff --git a/Client/Assembly-CSharp/UseButtonManager.cs b/Client/Assembly-CSharp/UseButtonManager.cs
new file mode 100644
index 0000000..c6a7f65
--- /dev/null
+++ b/Client/Assembly-CSharp/UseButtonManager.cs
@@ -0,0 +1,108 @@
+using System;
+using UnityEngine;
+
+public class UseButtonManager : MonoBehaviour
+{
+ private static readonly Color DisabledColor = new Color(1f, 1f, 1f, 0.3f);
+
+ private static readonly Color EnabledColor = new Color(1f, 1f, 1f, 1f);
+
+ public SpriteRenderer UseButton;
+
+ public Sprite UseImage;
+
+ public Sprite SabotageImage;
+
+ public Sprite VentImage;
+
+ public Sprite AdminMapImage;
+
+ public Sprite SecurityImage;
+
+ public Sprite OptionsImage;
+
+ private IUsable currentTarget;
+
+ public void SetTarget(IUsable target)
+ {
+ this.currentTarget = target;
+ if (target != null)
+ {
+ if (target is Vent)
+ {
+ this.UseButton.sprite = this.VentImage;
+ }
+ else if (target is MapConsole)
+ {
+ this.UseButton.sprite = this.AdminMapImage;
+ }
+ else if (target is OptionsConsole)
+ {
+ this.UseButton.sprite = this.OptionsImage;
+ }
+ else if (target is SystemConsole)
+ {
+ SystemConsole systemConsole = (SystemConsole)target;
+ if (systemConsole.name.StartsWith("Surv"))
+ {
+ this.UseButton.sprite = this.SecurityImage;
+ }
+ else if (systemConsole.name.StartsWith("TaskAdd"))
+ {
+ this.UseButton.sprite = this.OptionsImage;
+ }
+ else
+ {
+ this.UseButton.sprite = this.UseImage;
+ }
+ }
+ else
+ {
+ this.UseButton.sprite = this.UseImage;
+ }
+ this.UseButton.SetCooldownNormalizedUvs();
+ this.UseButton.material.SetFloat("_Percent", target.PercentCool);
+ this.UseButton.color = UseButtonManager.EnabledColor;
+ return;
+ }
+ if (PlayerControl.LocalPlayer.Data.IsImpostor && PlayerControl.LocalPlayer.CanMove)
+ {
+ this.UseButton.sprite = this.SabotageImage;
+ this.UseButton.SetCooldownNormalizedUvs();
+ this.UseButton.color = UseButtonManager.EnabledColor;
+ return;
+ }
+ this.UseButton.sprite = this.UseImage;
+ this.UseButton.color = UseButtonManager.DisabledColor;
+ }
+
+ public void DoClick()
+ {
+ if (!base.isActiveAndEnabled)
+ {
+ return;
+ }
+ if (!PlayerControl.LocalPlayer)
+ {
+ return;
+ }
+ GameData.PlayerInfo data = PlayerControl.LocalPlayer.Data;
+ if (this.currentTarget != null)
+ {
+ PlayerControl.LocalPlayer.UseClosest();
+ return;
+ }
+ if (data != null && data.IsImpostor)
+ {
+ DestroyableSingleton<HudManager>.Instance.ShowMap(delegate(MapBehaviour m)
+ {
+ m.ShowInfectedMap();
+ });
+ }
+ }
+
+ internal void Refresh()
+ {
+ this.SetTarget(this.currentTarget);
+ }
+}
diff --git a/Client/Assembly-CSharp/Vector2Range.cs b/Client/Assembly-CSharp/Vector2Range.cs
new file mode 100644
index 0000000..af83d56
--- /dev/null
+++ b/Client/Assembly-CSharp/Vector2Range.cs
@@ -0,0 +1,55 @@
+using System;
+using UnityEngine;
+
+[Serializable]
+public struct Vector2Range
+{
+ public float Width
+ {
+ get
+ {
+ return this.max.x - this.min.x;
+ }
+ }
+
+ public float Height
+ {
+ get
+ {
+ return this.max.y - this.min.y;
+ }
+ }
+
+ public Vector2 min;
+
+ public Vector2 max;
+
+ public Vector2Range(Vector2 min, Vector2 max)
+ {
+ this.min = min;
+ this.max = max;
+ }
+
+ public void LerpUnclamped(ref Vector3 output, float t, float z)
+ {
+ output.Set(Mathf.LerpUnclamped(this.min.x, this.max.x, t), Mathf.LerpUnclamped(this.min.y, this.max.y, t), z);
+ }
+
+ public void Lerp(ref Vector3 output, float t, float z)
+ {
+ output.Set(Mathf.Lerp(this.min.x, this.max.x, t), Mathf.Lerp(this.min.y, this.max.y, t), z);
+ }
+
+ public Vector2 Next()
+ {
+ return new Vector2(UnityEngine.Random.Range(this.min.x, this.max.x), UnityEngine.Random.Range(this.min.y, this.max.y));
+ }
+
+ public static Vector2 NextEdge()
+ {
+ float f = 6.2831855f * UnityEngine.Random.value;
+ float x = Mathf.Cos(f);
+ float y = Mathf.Sin(f);
+ return new Vector2(x, y);
+ }
+}
diff --git a/Client/Assembly-CSharp/VendingMinigame.cs b/Client/Assembly-CSharp/VendingMinigame.cs
new file mode 100644
index 0000000..19ad09b
--- /dev/null
+++ b/Client/Assembly-CSharp/VendingMinigame.cs
@@ -0,0 +1,188 @@
+using System;
+using System.Collections;
+using System.Linq;
+using UnityEngine;
+
+public class VendingMinigame : Minigame
+{
+ public static readonly string[] Letters = new string[]
+ {
+ "a",
+ "b",
+ "c"
+ };
+
+ public TextRenderer NumberText;
+
+ public SpriteRenderer TargetImage;
+
+ public string enteredCode = string.Empty;
+
+ private bool animating;
+
+ private bool done;
+
+ private string targetCode;
+
+ public SpriteRenderer AcceptButton;
+
+ public VendingSlot[] Slots;
+
+ public Sprite[] Drinks;
+
+ public Sprite[] DrawnDrinks;
+
+ public void OnEnable()
+ {
+ this.Begin(null);
+ }
+
+ public override void Begin(PlayerTask task)
+ {
+ base.Begin(task);
+ int num = this.Drinks.RandomIdx<Sprite>();
+ this.TargetImage.sprite = this.DrawnDrinks[num];
+ for (int i = 0; i < this.Drinks.Length; i++)
+ {
+ Sprite sprite = this.Drinks[i];
+ int num2;
+ while (!this.PickARandomSlot(sprite, out num2))
+ {
+ }
+ this.Slots[num2].DrinkImage.enabled = true;
+ this.Slots[num2].DrinkImage.sprite = sprite;
+ if (num == i)
+ {
+ this.targetCode = VendingMinigame.SlotIdToString(num2);
+ }
+ }
+ this.NumberText.Text = string.Empty;
+ }
+
+ private static int StringToSlotId(string code)
+ {
+ int num;
+ if (int.TryParse(code[0].ToString(), out num) || VendingMinigame.Letters.Any(new Func<string, bool>(code.EndsWith)))
+ {
+ return -1;
+ }
+ int num2 = VendingMinigame.Letters.IndexOf(new Predicate<string>(code.StartsWith));
+ return int.Parse(code[1].ToString()) - 1 + num2 * 4;
+ }
+
+ private static string SlotIdToString(int slotId)
+ {
+ int num = slotId % 4 + 1;
+ int num2 = slotId / 4;
+ return VendingMinigame.Letters[num2] + num;
+ }
+
+ private bool PickARandomSlot(Sprite drink, out int slotId)
+ {
+ slotId = this.Slots.RandomIdx<VendingSlot>();
+ return !this.Slots[slotId].DrinkImage.enabled;
+ }
+
+ public void EnterDigit(string s)
+ {
+ if (this.animating)
+ {
+ return;
+ }
+ if (this.done)
+ {
+ return;
+ }
+ if (this.enteredCode.Length >= 2)
+ {
+ base.StartCoroutine(this.BlinkAccept());
+ return;
+ }
+ this.enteredCode += s;
+ this.NumberText.Text = this.enteredCode;
+ }
+
+ public void ClearDigits()
+ {
+ if (this.animating)
+ {
+ return;
+ }
+ this.enteredCode = string.Empty;
+ this.NumberText.Text = string.Empty;
+ }
+
+ public void AcceptDigits()
+ {
+ if (this.animating)
+ {
+ return;
+ }
+ base.StartCoroutine(this.Animate());
+ }
+
+ private IEnumerator BlinkAccept()
+ {
+ int num;
+ for (int i = 0; i < 5; i = num)
+ {
+ this.AcceptButton.color = Color.gray;
+ yield return null;
+ yield return null;
+ this.AcceptButton.color = Color.white;
+ yield return null;
+ yield return null;
+ num = i + 1;
+ }
+ yield break;
+ }
+
+ private IEnumerator Animate()
+ {
+ this.animating = true;
+ int num = VendingMinigame.StringToSlotId(this.enteredCode);
+ if (num >= 0 && this.Slots[num].DrinkImage.enabled)
+ {
+ yield return Effects.All(new IEnumerator[]
+ {
+ this.CoBlinkVend(),
+ this.Slots[num].CoBuy()
+ });
+ if (this.targetCode == this.enteredCode)
+ {
+ this.done = true;
+ this.MyNormTask.NextStep();
+ yield return base.CoStartClose(0.25f);
+ }
+ }
+ else
+ {
+ WaitForSeconds wait = new WaitForSeconds(0.1f);
+ this.NumberText.Text = "XXXXXXXX";
+ yield return wait;
+ this.NumberText.Text = string.Empty;
+ yield return wait;
+ this.NumberText.Text = "XXXXXXXX";
+ yield return wait;
+ wait = null;
+ }
+ this.enteredCode = string.Empty;
+ this.NumberText.Text = this.enteredCode;
+ this.animating = false;
+ yield break;
+ }
+
+ private IEnumerator CoBlinkVend()
+ {
+ int num;
+ for (int i = 0; i < 5; i = num)
+ {
+ this.NumberText.Text = "Vending";
+ yield return Effects.Wait(0.1f);
+ this.NumberText.Text = string.Empty;
+ yield return Effects.Wait(0.1f);
+ num = i + 1;
+ }
+ yield break;
+ }
+}
diff --git a/Client/Assembly-CSharp/VendingSlot.cs b/Client/Assembly-CSharp/VendingSlot.cs
new file mode 100644
index 0000000..f2b43e6
--- /dev/null
+++ b/Client/Assembly-CSharp/VendingSlot.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Collections;
+using UnityEngine;
+
+public class VendingSlot : MonoBehaviour
+{
+ public SpriteRenderer DrinkImage;
+
+ public SpriteRenderer GlassImage;
+
+ public IEnumerator CoBuy()
+ {
+ yield return new WaitForLerp(0.75f, delegate(float v)
+ {
+ this.GlassImage.size = new Vector2(1f, Mathf.Lerp(1.7f, 0f, v));
+ this.GlassImage.transform.localPosition = new Vector3(0f, Mathf.Lerp(0f, 0.85f, v), -1f);
+ });
+ yield return Effects.Shake(this.DrinkImage.transform, 0.75f, 0.075f);
+ Vector3 localPosition = this.DrinkImage.transform.localPosition;
+ localPosition.z = -5f;
+ this.DrinkImage.transform.localPosition = localPosition;
+ Vector3 v2 = localPosition;
+ v2.y = -8f - localPosition.y;
+ yield return Effects.All(new IEnumerator[]
+ {
+ Effects.Slide2D(this.DrinkImage.transform, localPosition, v2, 0.75f),
+ Effects.Rotate2D(this.DrinkImage.transform, 0f, -FloatRange.Next(-45f, 45f), 0.75f)
+ });
+ yield return new WaitForLerp(0.75f, delegate(float v)
+ {
+ this.GlassImage.size = new Vector2(1f, Mathf.Lerp(0f, 1.7f, v));
+ this.GlassImage.transform.localPosition = new Vector3(0f, Mathf.Lerp(0.85f, 0f, v), -1f);
+ });
+ this.DrinkImage.enabled = false;
+ yield break;
+ }
+}
diff --git a/Client/Assembly-CSharp/Vent.cs b/Client/Assembly-CSharp/Vent.cs
new file mode 100644
index 0000000..ce9c525
--- /dev/null
+++ b/Client/Assembly-CSharp/Vent.cs
@@ -0,0 +1,163 @@
+using System;
+using PowerTools;
+using UnityEngine;
+
+public class Vent : MonoBehaviour, IUsable
+{
+ public float UsableDistance
+ {
+ get
+ {
+ return 0.75f;
+ }
+ }
+
+ public float PercentCool
+ {
+ get
+ {
+ return 0f;
+ }
+ }
+
+ public int Id;
+
+ public Vent Left;
+
+ public Vent Right;
+
+ public ButtonBehavior[] Buttons;
+
+ public AnimationClip EnterVentAnim;
+
+ public AnimationClip ExitVentAnim;
+
+ private static readonly Vector3 CollOffset = new Vector3(0f, -0.3636057f, 0f);
+
+ private SpriteRenderer myRend;
+
+ private void Start()
+ {
+ this.SetButtons(false);
+ this.myRend = base.GetComponent<SpriteRenderer>();
+ }
+
+ public void SetButtons(bool enabled)
+ {
+ Vent[] array = new Vent[]
+ {
+ this.Right,
+ this.Left
+ };
+ for (int i = 0; i < this.Buttons.Length; i++)
+ {
+ ButtonBehavior buttonBehavior = this.Buttons[i];
+ if (enabled)
+ {
+ Vent vent = array[i];
+ if (vent)
+ {
+ buttonBehavior.gameObject.SetActive(true);
+ Vector3 localPosition = (vent.transform.position - base.transform.position).normalized * 0.7f;
+ localPosition.y -= 0.08f;
+ localPosition.z = -10f;
+ buttonBehavior.transform.localPosition = localPosition;
+ buttonBehavior.transform.LookAt2d(vent.transform);
+ }
+ else
+ {
+ buttonBehavior.gameObject.SetActive(false);
+ }
+ }
+ else
+ {
+ buttonBehavior.gameObject.SetActive(false);
+ }
+ }
+ }
+
+ public float CanUse(GameData.PlayerInfo pc, out bool canUse, out bool couldUse)
+ {
+ float num = float.MaxValue;
+ PlayerControl @object = pc.Object;
+ couldUse = (pc.IsImpostor && !pc.IsDead && (@object.CanMove || @object.inVent));
+ canUse = couldUse;
+ if (canUse)
+ {
+ num = Vector2.Distance(@object.GetTruePosition(), base.transform.position);
+ canUse &= (num <= this.UsableDistance);
+ }
+ return num;
+ }
+
+ public void SetOutline(bool on, bool mainTarget)
+ {
+ this.myRend.material.SetFloat("_Outline", (float)(on ? 1 : 0));
+ this.myRend.material.SetColor("_OutlineColor", Color.red);
+ this.myRend.material.SetColor("_AddColor", mainTarget ? Color.red : Color.clear);
+ }
+
+ public void ClickRight()
+ {
+ if (this.Right)
+ {
+ Vent.DoMove(this.Right.transform.position - Vent.CollOffset);
+ this.SetButtons(false);
+ this.Right.SetButtons(true);
+ }
+ }
+
+ public void ClickLeft()
+ {
+ if (this.Left)
+ {
+ Vent.DoMove(this.Left.transform.position - Vent.CollOffset);
+ this.SetButtons(false);
+ this.Left.SetButtons(true);
+ }
+ }
+
+ private static void DoMove(Vector3 pos)
+ {
+ PlayerControl.LocalPlayer.NetTransform.RpcSnapTo(pos);
+ if (Constants.ShouldPlaySfx())
+ {
+ SoundManager.Instance.PlaySound(PlayerControl.LocalPlayer.VentMoveSounds.Random<AudioClip>(), false, 1f).pitch = FloatRange.Next(0.8f, 1.2f);
+ }
+ }
+
+ public void Use()
+ {
+ bool flag;
+ bool flag2;
+ this.CanUse(PlayerControl.LocalPlayer.Data, out flag, out flag2);
+ if (!flag)
+ {
+ return;
+ }
+ PlayerControl localPlayer = PlayerControl.LocalPlayer;
+ if (Constants.ShouldPlaySfx())
+ {
+ SoundManager.Instance.StopSound(localPlayer.VentEnterSound);
+ SoundManager.Instance.PlaySound(localPlayer.VentEnterSound, false, 1f).pitch = FloatRange.Next(0.8f, 1.2f);
+ }
+ if (localPlayer.inVent)
+ {
+ localPlayer.MyPhysics.RpcExitVent(this.Id);
+ this.SetButtons(false);
+ return;
+ }
+ localPlayer.MyPhysics.RpcEnterVent(this.Id);
+ this.SetButtons(true);
+ }
+
+ internal void EnterVent()
+ {
+ base.GetComponent<SpriteAnim>().Play(this.EnterVentAnim, 1f);
+ }
+
+ internal void ExitVent()
+ {
+ base.GetComponent<SpriteAnim>().Play(this.ExitVentAnim, 1f);
+ }
+}
diff --git a/Client/Assembly-CSharp/VersionShower.cs b/Client/Assembly-CSharp/VersionShower.cs
new file mode 100644
index 0000000..8c87390
--- /dev/null
+++ b/Client/Assembly-CSharp/VersionShower.cs
@@ -0,0 +1,19 @@
+using System;
+using UnityEngine;
+
+public class VersionShower : MonoBehaviour
+{
+ public TextRenderer text;
+
+ public void Start()
+ {
+ string str = "v" + Application.version;
+ str += "s";
+ if (!DetectTamper.Detect())
+ {
+ str += "h";
+ }
+ this.text.Text = str;
+ Screen.sleepTimeout = -1;
+ }
+}
diff --git a/Client/Assembly-CSharp/VerticalGauge.cs b/Client/Assembly-CSharp/VerticalGauge.cs
new file mode 100644
index 0000000..08ebfec
--- /dev/null
+++ b/Client/Assembly-CSharp/VerticalGauge.cs
@@ -0,0 +1,28 @@
+using System;
+using UnityEngine;
+
+public class VerticalGauge : MonoBehaviour
+{
+ public float value = 0.5f;
+
+ public float MaxValue = 1f;
+
+ public float maskScale = 1f;
+
+ public SpriteMask Mask;
+
+ private float lastValue = float.MinValue;
+
+ public void Update()
+ {
+ if (this.lastValue != this.value)
+ {
+ this.lastValue = this.value;
+ float num = Mathf.Clamp(this.lastValue / this.MaxValue, 0f, 1f) * this.maskScale;
+ Vector3 localScale = this.Mask.transform.localScale;
+ localScale.y = num;
+ this.Mask.transform.localScale = localScale;
+ this.Mask.transform.localPosition = new Vector3(0f, -this.Mask.sprite.bounds.size.y * (this.maskScale - num) / 2f, 0f);
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/VirtualJoystick.cs b/Client/Assembly-CSharp/VirtualJoystick.cs
new file mode 100644
index 0000000..25aaa72
--- /dev/null
+++ b/Client/Assembly-CSharp/VirtualJoystick.cs
@@ -0,0 +1,59 @@
+using System;
+using UnityEngine;
+
+public class VirtualJoystick : MonoBehaviour, IVirtualJoystick
+{
+ public Vector2 Delta { get; private set; }
+
+ public float InnerRadius = 0.64f;
+
+ public float OuterRadius = 1.28f;
+
+ public CircleCollider2D Outer;
+
+ public SpriteRenderer Inner;
+
+ private Controller myController = new Controller();
+
+ protected virtual void FixedUpdate()
+ {
+ this.myController.Update();
+ DragState dragState = this.myController.CheckDrag(this.Outer, false);
+ if (dragState - DragState.TouchStart <= 1)
+ {
+ float maxLength = this.OuterRadius - this.InnerRadius;
+ Vector2 vector = this.myController.DragPosition - base.transform.position;
+ float magnitude = vector.magnitude;
+ Vector2 a = new Vector2(Mathf.Sqrt(Mathf.Abs(vector.x)) * Mathf.Sign(vector.x), Mathf.Sqrt(Mathf.Abs(vector.y)) * Mathf.Sign(vector.y));
+ this.Delta = Vector2.ClampMagnitude(a / this.OuterRadius, 1f);
+ this.Inner.transform.localPosition = Vector3.ClampMagnitude(vector, maxLength) + Vector3.back;
+ return;
+ }
+ if (dragState != DragState.Released)
+ {
+ return;
+ }
+ this.Delta = Vector2.zero;
+ this.Inner.transform.localPosition = Vector3.back;
+ }
+
+ public virtual void UpdateJoystick(FingerBehaviour finger, Vector2 velocity, bool syncFinger)
+ {
+ Vector3 vector = this.Inner.transform.localPosition;
+ Vector3 vector2 = velocity.normalized * this.InnerRadius;
+ vector2.z = vector.z;
+ if (syncFinger)
+ {
+ vector = Vector3.Lerp(vector, vector2, Time.fixedDeltaTime * 5f);
+ this.Inner.transform.localPosition = vector;
+ vector = this.Inner.transform.position;
+ vector.z = -26f;
+ finger.transform.position = vector;
+ return;
+ }
+ if (this.Inner.gameObject != finger.gameObject)
+ {
+ this.Inner.transform.localPosition = vector2;
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/VoteBanSystem.cs b/Client/Assembly-CSharp/VoteBanSystem.cs
new file mode 100644
index 0000000..23d030f
--- /dev/null
+++ b/Client/Assembly-CSharp/VoteBanSystem.cs
@@ -0,0 +1,111 @@
+using System;
+using System.Collections.Generic;
+using Hazel;
+using InnerNet;
+
+public class VoteBanSystem : InnerNetObject
+{
+ public static VoteBanSystem Instance;
+
+ public Dictionary<int, int[]> Votes = new Dictionary<int, int[]>();
+
+ public enum RpcCalls
+ {
+ AddVote
+ }
+
+ public void Awake()
+ {
+ VoteBanSystem.Instance = this;
+ }
+
+ public void CmdAddVote(int clientId)
+ {
+ this.AddVote(AmongUsClient.Instance.ClientId, clientId);
+ MessageWriter messageWriter = AmongUsClient.Instance.StartRpc(this.NetId, 0, SendOption.Reliable);
+ messageWriter.Write(AmongUsClient.Instance.ClientId);
+ messageWriter.Write(clientId);
+ messageWriter.EndMessage();
+ }
+
+ private void AddVote(int srcClient, int clientId)
+ {
+ int[] array;
+ if (!this.Votes.TryGetValue(clientId, out array))
+ {
+ array = (this.Votes[clientId] = new int[3]);
+ }
+ int num = -1;
+ for (int i = 0; i < array.Length; i++)
+ {
+ int num2 = array[i];
+ if (num2 == srcClient)
+ {
+ break;
+ }
+ if (num2 == 0)
+ {
+ num = i;
+ break;
+ }
+ }
+ if (num != -1)
+ {
+ array[num] = srcClient;
+ base.SetDirtyBit(1U);
+ if (num == array.Length - 1)
+ {
+ AmongUsClient.Instance.KickPlayer(clientId, false);
+ }
+ }
+ }
+
+ public bool HasMyVote(int clientId)
+ {
+ int[] array;
+ return this.Votes.TryGetValue(clientId, out array) && Array.IndexOf<int>(array, AmongUsClient.Instance.ClientId) != -1;
+ }
+
+ public override void HandleRpc(byte callId, MessageReader reader)
+ {
+ if (callId == 0)
+ {
+ int srcClient = reader.ReadInt32();
+ int clientId = reader.ReadInt32();
+ this.AddVote(srcClient, clientId);
+ }
+ }
+
+ public override bool Serialize(MessageWriter writer, bool initialState)
+ {
+ writer.Write((byte)this.Votes.Count);
+ foreach (KeyValuePair<int, int[]> keyValuePair in this.Votes)
+ {
+ writer.Write(keyValuePair.Key);
+ for (int i = 0; i < 3; i++)
+ {
+ writer.WritePacked(keyValuePair.Value[i]);
+ }
+ }
+ this.DirtyBits = 0U;
+ return true;
+ }
+
+ public override void Deserialize(MessageReader reader, bool initialState)
+ {
+ int num = (int)reader.ReadByte();
+ for (int i = 0; i < num; i++)
+ {
+ int key = reader.ReadInt32();
+ int[] array;
+ if (!this.Votes.TryGetValue(key, out array))
+ {
+ array = (this.Votes[key] = new int[3]);
+ }
+ for (int j = 0; j < 3; j++)
+ {
+ array[j] = reader.ReadPackedInt32();
+ }
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/WaitForHostPopup.cs b/Client/Assembly-CSharp/WaitForHostPopup.cs
new file mode 100644
index 0000000..5ccade5
--- /dev/null
+++ b/Client/Assembly-CSharp/WaitForHostPopup.cs
@@ -0,0 +1,27 @@
+using System;
+using InnerNet;
+using UnityEngine;
+
+public class WaitForHostPopup : DestroyableSingleton<WaitForHostPopup>
+{
+ public GameObject Content;
+
+ public void Show()
+ {
+ if (AmongUsClient.Instance && AmongUsClient.Instance.ClientId > 0)
+ {
+ this.Content.SetActive(true);
+ }
+ }
+
+ public void ExitGame()
+ {
+ AmongUsClient.Instance.ExitGame(DisconnectReasons.ExitGame);
+ this.Content.SetActive(false);
+ }
+
+ public void Hide()
+ {
+ this.Content.SetActive(false);
+ }
+}
diff --git a/Client/Assembly-CSharp/WaitForLerp.cs b/Client/Assembly-CSharp/WaitForLerp.cs
new file mode 100644
index 0000000..97c8bcd
--- /dev/null
+++ b/Client/Assembly-CSharp/WaitForLerp.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Collections;
+using UnityEngine;
+
+public class WaitForLerp : IEnumerator
+{
+ public object Current
+ {
+ get
+ {
+ return null;
+ }
+ }
+
+ private float duration;
+
+ private float timer;
+
+ private Action<float> act;
+
+ public WaitForLerp(float seconds, Action<float> act)
+ {
+ this.duration = seconds;
+ this.act = act;
+ }
+
+ public bool MoveNext()
+ {
+ this.timer = Mathf.Min(this.timer + Time.deltaTime, this.duration);
+ this.act(this.timer / this.duration);
+ return this.timer < this.duration;
+ }
+
+ public void Reset()
+ {
+ this.timer = 0f;
+ }
+}
diff --git a/Client/Assembly-CSharp/WeaponsMinigame.cs b/Client/Assembly-CSharp/WeaponsMinigame.cs
new file mode 100644
index 0000000..c6dc8f6
--- /dev/null
+++ b/Client/Assembly-CSharp/WeaponsMinigame.cs
@@ -0,0 +1,149 @@
+using System;
+using System.Collections;
+using UnityEngine;
+
+public class WeaponsMinigame : Minigame
+{
+ public FloatRange XSpan = new FloatRange(-1.15f, 1.15f);
+
+ public FloatRange YSpan = new FloatRange(-1.15f, 1.15f);
+
+ public FloatRange TimeToSpawn;
+
+ public ObjectPoolBehavior asteroidPool;
+
+ public TextController ScoreText;
+
+ public SpriteRenderer TargetReticle;
+
+ public LineRenderer TargetLines;
+
+ private Vector3 TargetCenter;
+
+ public Collider2D BackgroundCol;
+
+ public SpriteRenderer Background;
+
+ public Controller myController = new Controller();
+
+ private float Timer;
+
+ public AudioClip ShootSound;
+
+ public AudioClip[] ExplodeSounds;
+
+ public override void Begin(PlayerTask task)
+ {
+ base.Begin(task);
+ this.ScoreText.Text = "Destroyed: " + this.MyNormTask.taskStep;
+ this.TimeToSpawn.Next();
+ }
+
+ protected override IEnumerator CoAnimateOpen()
+ {
+ for (float timer = 0f; timer < 0.1f; timer += Time.deltaTime)
+ {
+ float num = timer / 0.1f;
+ base.transform.localScale = new Vector3(num, 0.1f, num);
+ yield return null;
+ }
+ for (float timer = 0.010000001f; timer < 0.1f; timer += Time.deltaTime)
+ {
+ float y = timer / 0.1f;
+ base.transform.localScale = new Vector3(1f, y, 1f);
+ yield return null;
+ }
+ base.transform.localScale = new Vector3(1f, 1f, 1f);
+ yield break;
+ }
+
+ protected override IEnumerator CoDestroySelf()
+ {
+ for (float timer = 0.010000001f; timer < 0.1f; timer += Time.deltaTime)
+ {
+ float y = 1f - timer / 0.1f;
+ base.transform.localScale = new Vector3(1f, y, 1f);
+ yield return null;
+ }
+ for (float timer = 0f; timer < 0.1f; timer += Time.deltaTime)
+ {
+ float num = 1f - timer / 0.1f;
+ base.transform.localScale = new Vector3(num, 0.1f, num);
+ yield return null;
+ }
+ UnityEngine.Object.Destroy(base.gameObject);
+ yield break;
+ }
+
+ public void FixedUpdate()
+ {
+ this.Background.color = Color.Lerp(Palette.ClearWhite, Color.white, Mathf.Sin(Time.time * 3f) * 0.1f + 0.79999995f);
+ if (this.MyNormTask && this.MyNormTask.IsComplete)
+ {
+ return;
+ }
+ this.Timer += Time.fixedDeltaTime;
+ if (this.Timer >= this.TimeToSpawn.Last)
+ {
+ this.Timer = 0f;
+ this.TimeToSpawn.Next();
+ if (this.asteroidPool.InUse < this.MyNormTask.MaxStep - this.MyNormTask.TaskStep)
+ {
+ Asteroid ast = this.asteroidPool.Get<Asteroid>();
+ ast.transform.localPosition = new Vector3(this.XSpan.max, this.YSpan.Next(), -1f);
+ ast.TargetPosition = new Vector3(this.XSpan.min, this.YSpan.Next(), -1f);
+ ast.GetComponent<ButtonBehavior>().OnClick.AddListener(delegate()
+ {
+ this.BreakApart(ast);
+ });
+ }
+ }
+ this.myController.Update();
+ if (this.myController.CheckDrag(this.BackgroundCol, false) == DragState.TouchStart)
+ {
+ if (Constants.ShouldPlaySfx())
+ {
+ SoundManager.Instance.PlaySound(this.ShootSound, false, 1f);
+ }
+ Vector3 vector = this.myController.DragPosition - base.transform.position;
+ vector.z = -2f;
+ this.TargetReticle.transform.localPosition = vector;
+ vector.z = 0f;
+ this.TargetLines.SetPosition(1, vector);
+ if (!ShipStatus.Instance.WeaponsImage.IsPlaying(null))
+ {
+ ShipStatus.Instance.FireWeapon();
+ PlayerControl.LocalPlayer.RpcPlayAnimation(6);
+ }
+ }
+ }
+
+ public void BreakApart(Asteroid ast)
+ {
+ if (Constants.ShouldPlaySfx())
+ {
+ SoundManager.Instance.PlaySound(this.ExplodeSounds.Random<AudioClip>(), false, 1f).pitch = FloatRange.Next(0.8f, 1.2f);
+ }
+ if (!this.MyNormTask.IsComplete)
+ {
+ base.StartCoroutine(ast.CoBreakApart());
+ if (this.MyNormTask)
+ {
+ this.MyNormTask.NextStep();
+ this.ScoreText.Text = "Destroyed: " + this.MyNormTask.taskStep;
+ }
+ if (this.MyNormTask && this.MyNormTask.IsComplete)
+ {
+ base.StartCoroutine(base.CoStartClose(0.75f));
+ foreach (PoolableBehavior poolableBehavior in this.asteroidPool.activeChildren)
+ {
+ Asteroid asteroid = (Asteroid)poolableBehavior;
+ if (!(asteroid == ast))
+ {
+ base.StartCoroutine(asteroid.CoBreakApart());
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/WeatherMinigame.cs b/Client/Assembly-CSharp/WeatherMinigame.cs
new file mode 100644
index 0000000..fe02976
--- /dev/null
+++ b/Client/Assembly-CSharp/WeatherMinigame.cs
@@ -0,0 +1,34 @@
+using System;
+using UnityEngine;
+
+public class WeatherMinigame : Minigame
+{
+ public float RefuelDuration = 5f;
+
+ public VerticalGauge destGauge;
+
+ private bool isDown;
+
+ private float timer;
+
+ public void FixedUpdate()
+ {
+ if (this.isDown && this.timer < 1f)
+ {
+ this.timer += Time.fixedDeltaTime / this.RefuelDuration;
+ this.MyNormTask.Data[0] = (byte)Mathf.Min(255f, this.timer * 255f);
+ if (this.timer >= 1f)
+ {
+ this.timer = 1f;
+ this.MyNormTask.NextStep();
+ base.StartCoroutine(base.CoStartClose(0.75f));
+ }
+ }
+ this.destGauge.value = this.timer;
+ }
+
+ public void StartStopFill()
+ {
+ this.isDown = !this.isDown;
+ }
+}
diff --git a/Client/Assembly-CSharp/WinningPlayerData.cs b/Client/Assembly-CSharp/WinningPlayerData.cs
new file mode 100644
index 0000000..dffd5e5
--- /dev/null
+++ b/Client/Assembly-CSharp/WinningPlayerData.cs
@@ -0,0 +1,36 @@
+using System;
+
+public class WinningPlayerData
+{
+ public string Name;
+
+ public bool IsDead;
+
+ public bool IsImpostor;
+
+ public int ColorId;
+
+ public uint SkinId;
+
+ public uint HatId;
+
+ public uint PetId;
+
+ public bool IsYou;
+
+ public WinningPlayerData()
+ {
+ }
+
+ public WinningPlayerData(GameData.PlayerInfo player)
+ {
+ this.IsYou = (player.Object == PlayerControl.LocalPlayer);
+ this.Name = player.PlayerName;
+ this.IsDead = (player.IsDead || player.Disconnected);
+ this.IsImpostor = player.IsImpostor;
+ this.ColorId = (int)player.ColorId;
+ this.SkinId = player.SkinId;
+ this.PetId = player.PetId;
+ this.HatId = player.HatId;
+ }
+}
diff --git a/Client/Assembly-CSharp/Wire.cs b/Client/Assembly-CSharp/Wire.cs
new file mode 100644
index 0000000..055bc41
--- /dev/null
+++ b/Client/Assembly-CSharp/Wire.cs
@@ -0,0 +1,61 @@
+using System;
+using UnityEngine;
+
+public class Wire : MonoBehaviour
+{
+ public Vector2 BaseWorldPos { get; internal set; }
+
+ private const int WireDepth = -14;
+
+ public SpriteRenderer Liner;
+
+ public SpriteRenderer ColorBase;
+
+ public SpriteRenderer ColorEnd;
+
+ public Collider2D hitbox;
+
+ public SpriteRenderer WireTip;
+
+ public sbyte WireId;
+
+ public void Start()
+ {
+ this.BaseWorldPos = base.transform.position;
+ }
+
+ public void ResetLine(Vector3 targetWorldPos, bool reset = false)
+ {
+ if (reset)
+ {
+ this.Liner.transform.localScale = new Vector3(0f, 0f, 0f);
+ this.WireTip.transform.eulerAngles = Vector3.zero;
+ this.WireTip.transform.position = base.transform.position;
+ return;
+ }
+ Vector2 vector = targetWorldPos - base.transform.position;
+ Vector2 normalized = vector.normalized;
+ Vector3 localPosition = default(Vector3);
+ localPosition = vector - normalized * 0.075f;
+ localPosition.z = -0.01f;
+ this.WireTip.transform.localPosition = localPosition;
+ float magnitude = vector.magnitude;
+ this.Liner.transform.localScale = new Vector3(magnitude, 1f, 1f);
+ this.Liner.transform.localPosition = vector / 2f;
+ this.WireTip.transform.LookAt2d(targetWorldPos);
+ this.Liner.transform.localEulerAngles = new Vector3(0f, 0f, Vector2.SignedAngle(Vector2.right, vector));
+ }
+
+ public void ConnectRight(WireNode node)
+ {
+ Vector3 position = node.transform.position;
+ this.ResetLine(position, false);
+ }
+
+ public void SetColor(Color color)
+ {
+ this.Liner.material.SetColor("_Color", color);
+ this.ColorBase.color = color;
+ this.ColorEnd.color = color;
+ }
+}
diff --git a/Client/Assembly-CSharp/WireMinigame.cs b/Client/Assembly-CSharp/WireMinigame.cs
new file mode 100644
index 0000000..27d0ecc
--- /dev/null
+++ b/Client/Assembly-CSharp/WireMinigame.cs
@@ -0,0 +1,157 @@
+using System;
+using UnityEngine;
+
+public class WireMinigame : Minigame
+{
+ private static readonly Color[] colors = new Color[]
+ {
+ Color.red,
+ Color.blue,
+ Color.yellow,
+ Color.magenta
+ };
+
+ public Wire[] LeftNodes;
+
+ public WireNode[] RightNodes;
+
+ public SpriteRenderer[] LeftLights;
+
+ public SpriteRenderer[] RightLights;
+
+ private Controller myController = new Controller();
+
+ private sbyte[] ExpectedWires = new sbyte[4];
+
+ private sbyte[] ActualWires = new sbyte[4];
+
+ public AudioClip[] WireSounds;
+
+ private bool TaskIsForThisPanel()
+ {
+ return this.MyNormTask.taskStep < this.MyNormTask.Data.Length && !this.MyNormTask.IsComplete && (int)this.MyNormTask.Data[this.MyNormTask.taskStep] == base.ConsoleId;
+ }
+
+ public override void Begin(PlayerTask task)
+ {
+ base.Begin(task);
+ IntRange.FillRandomRange(this.ExpectedWires);
+ for (int i = 0; i < this.LeftNodes.Length; i++)
+ {
+ this.ActualWires[i] = -1;
+ int num = (int)this.ExpectedWires[i];
+ Wire wire = this.LeftNodes[i];
+ wire.SetColor(WireMinigame.colors[num]);
+ wire.WireId = (sbyte)i;
+ this.RightNodes[i].SetColor(WireMinigame.colors[i]);
+ this.RightNodes[i].WireId = (sbyte)i;
+ int num2 = (int)this.ActualWires[i];
+ if (num2 > -1)
+ {
+ wire.ConnectRight(this.RightNodes[num2]);
+ }
+ else
+ {
+ wire.ResetLine(Vector3.zero, true);
+ }
+ }
+ this.UpdateLights();
+ }
+
+ public void Update()
+ {
+ if (!this.TaskIsForThisPanel())
+ {
+ return;
+ }
+ this.myController.Update();
+ base.transform.position;
+ for (int i = 0; i < this.LeftNodes.Length; i++)
+ {
+ Wire wire = this.LeftNodes[i];
+ DragState dragState = this.myController.CheckDrag(wire.hitbox, false);
+ if (dragState != DragState.Dragging)
+ {
+ if (dragState == DragState.Released)
+ {
+ if (this.ActualWires[(int)wire.WireId] == -1)
+ {
+ wire.ResetLine(wire.BaseWorldPos, true);
+ }
+ else if (Constants.ShouldPlaySfx())
+ {
+ SoundManager.Instance.PlaySound(this.WireSounds.Random<AudioClip>(), false, 1f);
+ }
+ this.CheckTask();
+ }
+ }
+ else
+ {
+ Vector2 vector = this.myController.DragPosition;
+ WireNode wireNode = this.CheckRightSide(vector);
+ if (wireNode)
+ {
+ vector = wireNode.transform.position;
+ this.ActualWires[(int)wire.WireId] = wireNode.WireId;
+ }
+ else
+ {
+ vector -= wire.BaseWorldPos.normalized * 0.05f;
+ this.ActualWires[(int)wire.WireId] = -1;
+ }
+ wire.ResetLine(vector, false);
+ }
+ }
+ this.UpdateLights();
+ }
+
+ private void UpdateLights()
+ {
+ for (int i = 0; i < this.ActualWires.Length; i++)
+ {
+ Color color = Color.yellow;
+ color *= 1f - Mathf.PerlinNoise((float)i, Time.time * 35f) * 0.3f;
+ color.a = 1f;
+ if (this.ActualWires[i] != this.ExpectedWires[i])
+ {
+ this.RightLights[(int)this.ExpectedWires[i]].color = new Color(0.2f, 0.2f, 0.2f);
+ }
+ else
+ {
+ this.RightLights[(int)this.ExpectedWires[i]].color = color;
+ }
+ this.LeftLights[i].color = color;
+ }
+ }
+
+ private WireNode CheckRightSide(Vector2 pos)
+ {
+ for (int i = 0; i < this.RightNodes.Length; i++)
+ {
+ WireNode wireNode = this.RightNodes[i];
+ if (wireNode.hitbox.OverlapPoint(pos))
+ {
+ return wireNode;
+ }
+ }
+ return null;
+ }
+
+ private void CheckTask()
+ {
+ bool flag = true;
+ for (int i = 0; i < this.ActualWires.Length; i++)
+ {
+ if (this.ActualWires[i] != this.ExpectedWires[i])
+ {
+ flag = false;
+ break;
+ }
+ }
+ if (flag)
+ {
+ this.MyNormTask.NextStep();
+ this.Close();
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/WireNode.cs b/Client/Assembly-CSharp/WireNode.cs
new file mode 100644
index 0000000..04db0bc
--- /dev/null
+++ b/Client/Assembly-CSharp/WireNode.cs
@@ -0,0 +1,19 @@
+using System;
+using UnityEngine;
+
+public class WireNode : MonoBehaviour
+{
+ public Collider2D hitbox;
+
+ public SpriteRenderer[] WireColors;
+
+ public sbyte WireId;
+
+ internal void SetColor(Color color)
+ {
+ for (int i = 0; i < this.WireColors.Length; i++)
+ {
+ this.WireColors[i].color = color;
+ }
+ }
+}
diff --git a/Client/Assembly-CSharp/XXHash.cs b/Client/Assembly-CSharp/XXHash.cs
new file mode 100644
index 0000000..5845560
--- /dev/null
+++ b/Client/Assembly-CSharp/XXHash.cs
@@ -0,0 +1,189 @@
+using System;
+
+public class XXHash
+{
+ private uint seed;
+
+ private const uint PRIME32_1 = 2654435761U;
+
+ private const uint PRIME32_2 = 2246822519U;
+
+ private const uint PRIME32_3 = 3266489917U;
+
+ private const uint PRIME32_4 = 668265263U;
+
+ private const uint PRIME32_5 = 374761393U;
+
+ public XXHash(int seed)
+ {
+ this.seed = (uint)seed;
+ }
+
+ public uint GetHash(byte[] buf)
+ {
+ int i = 0;
+ int num = buf.Length;
+ uint num3;
+ if (num >= 16)
+ {
+ int num2 = num - 16;
+ uint value = this.seed + 2654435761U + 2246822519U;
+ uint value2 = this.seed + 2246822519U;
+ uint value3 = this.seed;
+ uint value4 = this.seed - 2654435761U;
+ do
+ {
+ value = XXHash.CalcSubHash(value, buf, i);
+ i += 4;
+ value2 = XXHash.CalcSubHash(value2, buf, i);
+ i += 4;
+ value3 = XXHash.CalcSubHash(value3, buf, i);
+ i += 4;
+ value4 = XXHash.CalcSubHash(value4, buf, i);
+ i += 4;
+ }
+ while (i <= num2);
+ num3 = XXHash.RotateLeft(value, 1) + XXHash.RotateLeft(value2, 7) + XXHash.RotateLeft(value3, 12) + XXHash.RotateLeft(value4, 18);
+ }
+ else
+ {
+ num3 = this.seed + 374761393U;
+ }
+ num3 += (uint)num;
+ while (i <= num - 4)
+ {
+ num3 += BitConverter.ToUInt32(buf, i) * 3266489917U;
+ num3 = XXHash.RotateLeft(num3, 17) * 668265263U;
+ i += 4;
+ }
+ while (i < num)
+ {
+ num3 += (uint)buf[i] * 374761393U;
+ num3 = XXHash.RotateLeft(num3, 11) * 2654435761U;
+ i++;
+ }
+ num3 ^= num3 >> 15;
+ num3 *= 2246822519U;
+ num3 ^= num3 >> 13;
+ num3 *= 3266489917U;
+ return num3 ^ num3 >> 16;
+ }
+
+ public uint GetHash(params uint[] buf)
+ {
+ int i = 0;
+ int num = buf.Length;
+ uint num3;
+ if (num >= 4)
+ {
+ int num2 = num - 4;
+ uint value = this.seed + 2654435761U + 2246822519U;
+ uint value2 = this.seed + 2246822519U;
+ uint value3 = this.seed;
+ uint value4 = this.seed - 2654435761U;
+ do
+ {
+ value = XXHash.CalcSubHash(value, buf[i]);
+ i++;
+ value2 = XXHash.CalcSubHash(value2, buf[i]);
+ i++;
+ value3 = XXHash.CalcSubHash(value3, buf[i]);
+ i++;
+ value4 = XXHash.CalcSubHash(value4, buf[i]);
+ i++;
+ }
+ while (i <= num2);
+ num3 = XXHash.RotateLeft(value, 1) + XXHash.RotateLeft(value2, 7) + XXHash.RotateLeft(value3, 12) + XXHash.RotateLeft(value4, 18);
+ }
+ else
+ {
+ num3 = this.seed + 374761393U;
+ }
+ num3 += (uint)(num * 4);
+ while (i < num)
+ {
+ num3 += buf[i] * 3266489917U;
+ num3 = XXHash.RotateLeft(num3, 17) * 668265263U;
+ i++;
+ }
+ num3 ^= num3 >> 15;
+ num3 *= 2246822519U;
+ num3 ^= num3 >> 13;
+ num3 *= 3266489917U;
+ return num3 ^ num3 >> 16;
+ }
+
+ public uint GetHash(params int[] buf)
+ {
+ int i = 0;
+ int num = buf.Length;
+ uint num3;
+ if (num >= 4)
+ {
+ int num2 = num - 4;
+ uint value = this.seed + 2654435761U + 2246822519U;
+ uint value2 = this.seed + 2246822519U;
+ uint value3 = this.seed;
+ uint value4 = this.seed - 2654435761U;
+ do
+ {
+ value = XXHash.CalcSubHash(value, (uint)buf[i]);
+ i++;
+ value2 = XXHash.CalcSubHash(value2, (uint)buf[i]);
+ i++;
+ value3 = XXHash.CalcSubHash(value3, (uint)buf[i]);
+ i++;
+ value4 = XXHash.CalcSubHash(value4, (uint)buf[i]);
+ i++;
+ }
+ while (i <= num2);
+ num3 = XXHash.RotateLeft(value, 1) + XXHash.RotateLeft(value2, 7) + XXHash.RotateLeft(value3, 12) + XXHash.RotateLeft(value4, 18);
+ }
+ else
+ {
+ num3 = this.seed + 374761393U;
+ }
+ num3 += (uint)(num * 4);
+ while (i < num)
+ {
+ num3 += (uint)(buf[i] * -1028477379);
+ num3 = XXHash.RotateLeft(num3, 17) * 668265263U;
+ i++;
+ }
+ num3 ^= num3 >> 15;
+ num3 *= 2246822519U;
+ num3 ^= num3 >> 13;
+ num3 *= 3266489917U;
+ return num3 ^ num3 >> 16;
+ }
+
+ public uint GetHash(int buf)
+ {
+ uint num = XXHash.RotateLeft(this.seed + 374761393U + 4U + (uint)(buf * -1028477379), 17) * 668265263U;
+ uint num2 = (num ^ num >> 15) * 2246822519U;
+ uint num3 = (num2 ^ num2 >> 13) * 3266489917U;
+ return num3 ^ num3 >> 16;
+ }
+
+ private static uint CalcSubHash(uint value, byte[] buf, int index)
+ {
+ uint num = BitConverter.ToUInt32(buf, index);
+ value += num * 2246822519U;
+ value = XXHash.RotateLeft(value, 13);
+ value *= 2654435761U;
+ return value;
+ }
+
+ private static uint CalcSubHash(uint value, uint read_value)
+ {
+ value += read_value * 2246822519U;
+ value = XXHash.RotateLeft(value, 13);
+ value *= 2654435761U;
+ return value;
+ }
+
+ private static uint RotateLeft(uint value, int count)
+ {
+ return value << count | value >> 32 - count;
+ }
+}
diff --git a/Client/Assembly-CSharp/obj/Debug/Assembly-CSharp.csproj.CoreCompileInputs.cache b/Client/Assembly-CSharp/obj/Debug/Assembly-CSharp.csproj.CoreCompileInputs.cache
new file mode 100644
index 0000000..2d286a7
--- /dev/null
+++ b/Client/Assembly-CSharp/obj/Debug/Assembly-CSharp.csproj.CoreCompileInputs.cache
@@ -0,0 +1 @@
+b8fad2e40478c2524efc69c84e4392785708d392
diff --git a/Client/Assembly-CSharp/obj/Debug/Assembly-CSharp.csprojAssemblyReference.cache b/Client/Assembly-CSharp/obj/Debug/Assembly-CSharp.csprojAssemblyReference.cache
new file mode 100644
index 0000000..528e904
--- /dev/null
+++ b/Client/Assembly-CSharp/obj/Debug/Assembly-CSharp.csprojAssemblyReference.cache
Binary files differ