using System; using System.Collections; using System.Collections.Generic; using System.Linq; using Assets.CoreScripts; using Hazel; using InnerNet; using PowerTools; using UnityEngine; // 这个结构没有要同步的数据,但是重写了handleRpc用来响应Rpc调用,所以命名为control // 是*角色*的根结构,包括了playerPhysics、CustomNetworkTransform等需要同步的数据 public class PlayerControl : InnerNetObject { public bool CanMove { get { return this.moveable && !Minigame.Instance && (!DestroyableSingleton.InstanceExists || (!DestroyableSingleton.Instance.Chat.IsOpen && !DestroyableSingleton.Instance.KillOverlay.IsOpen && !DestroyableSingleton.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 myTasks = new List(); [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 AllPlayerControls = new List(); private Dictionary cache = new Dictionary(PlayerControl.ColliderComparer.Instance); private List itemsInRange = new List(); private List newItemsInRange = new List(); private byte scannerCount; private int LastStartCounter; public class ColliderComparer : IEqualityComparer { 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 { 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 void SetKillTimer(float time) { this.killTimer = time; if (PlayerControl.GameOptions.KillCooldown > 0f) { DestroyableSingleton.Instance.KillButton.SetCoolDown(this.killTimer, PlayerControl.GameOptions.KillCooldown); return; } DestroyableSingleton.Instance.KillButton.SetCoolDown(0f, PlayerControl.GameOptions.KillCooldown); } private void Awake() { this.myRend = base.GetComponent(); this.MyPhysics = base.GetComponent(); this.NetTransform = base.GetComponent(); this.Collider = base.GetComponent(); PlayerControl.AllPlayerControls.Add(this); } private void Start() { this.RemainingEmergencies = PlayerControl.GameOptions.NumEmergencyMeetings; if (base.AmOwner) { this.myLight = UnityEngine.Object.Instantiate(this.LightPrefab); this.myLight.transform.SetParent(base.transform); this.myLight.transform.localPosition = this.Collider.offset; PlayerControl.LocalPlayer = this; Camera.main.GetComponent().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.Instance.KillButton.SetTarget(target); } else { DestroyableSingleton.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()); } 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(); 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.Instance.UseButton.SetTarget(usable); DestroyableSingleton.Instance.ReportButton.SetActive(flag2); return; } this.closest = null; DestroyableSingleton.Instance.UseButton.SetTarget(null); DestroyableSingleton.Instance.ReportButton.SetActive(false); } } public void UseClosest() { if (this.closest != null) { this.closest.Use(); } this.closest = null; DestroyableSingleton.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(); if (component && !component.Reported) { component.OnClick(); if (component.Reported) { break; } } } } } public void PlayStepSound() { if (!Constants.ShouldPlaySfx()) { return; } if (DestroyableSingleton.InstanceExists && PlayerControl.LocalPlayer == this) { ShipRoom lastRoom = DestroyableSingleton.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 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.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.Instance.KillButton.gameObject.SetActive(false); } DestroyableSingleton.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(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(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.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.Instance.KillButton.gameObject.SetActive(false); } } public void Die(DeathReason reason) { if (!DestroyableSingleton.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().material.SetInt("_Mask", 0); if (base.AmOwner) { DestroyableSingleton.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().material.SetInt("_Mask", 4); if (base.AmOwner) { DestroyableSingleton.Instance.KillButton.gameObject.SetActive(this.Data.IsImpostor); DestroyableSingleton.Instance.Chat.ForceClosed(); DestroyableSingleton.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.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.Instance.MapButton.gameObject.SetActive(true); DestroyableSingleton.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.transform.SetParent(PlayerControl.LocalPlayer.transform, false); importantTextTask.Text = DestroyableSingleton.Instance.GetString(StringNames.ImpostorTask, Array.Empty()) + "\r\n[FFFFFFFF]" + DestroyableSingleton.Instance.GetString(StringNames.FakeTasks, Array.Empty()); this.myTasks.Insert(0, importantTextTask); DestroyableSingleton.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.InstanceExists) { List 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(); } 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(); } base.StopAllCoroutines(); DestroyableSingleton.Instance.StartCoroutine(DestroyableSingleton.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.Instance.ShadowQuad.gameObject.SetActive(false); ImportantTextTask importantTextTask = new GameObject("_Player").AddComponent(); importantTextTask.transform.SetParent(base.transform, false); if (this.Data.IsImpostor) { this.ClearTasks(); importantTextTask.Text = DestroyableSingleton.Instance.GetString(StringNames.GhostImpostor, Array.Empty()); } else if (!PlayerControl.GameOptions.GhostsDoTasks) { this.ClearTasks(); importantTextTask.Text = DestroyableSingleton.Instance.GetString(StringNames.GhostIgnoreTasks, Array.Empty()); } else { importantTextTask.Text = DestroyableSingleton.Instance.GetString(StringNames.GhostDoTasks, Array.Empty()); } this.myTasks.Insert(0, importantTextTask); } } public void CheckName(string name) { List 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().material.SetInt("_Mask", 4); } public void CheckColor(byte bodyColor) { List 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(); } 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(DestroyableSingleton.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.InstanceExists) { return; } PlayerControl.SetPetImage(DestroyableSingleton.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.InstanceExists) { return; } PlayerControl.SetSkinImage(DestroyableSingleton.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.InstanceExists) { return; } PlayerControl.SetHatImage(DestroyableSingleton.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.TaskIsEmergency))) { return; } if (this.Data.IsDead) { return; } MeetingRoomManager.Instance.AssignSelf(this, target); if (!AmongUsClient.Instance.AmHost) { return; } if (ShipStatus.Instance.CheckTaskCompletion()) { return; } DestroyableSingleton.Instance.OpenMeetingRoom(this); this.RpcStartMeeting(target); } public IEnumerator CoStartMeeting(GameData.PlayerInfo target) { DestroyableSingleton.Instance.WriteMeetingStarted(target == null); while (!MeetingHud.Instance) { yield return null; } MeetingRoomManager.Instance.RemoveSelf(); DeadBody[] array = UnityEngine.Object.FindObjectsOfType(); 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().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.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.Instance.ShadowQuad.gameObject.SetActive(false); target.nameText.GetComponent().material.SetInt("_Mask", 0); DestroyableSingleton.Instance.KillOverlay.ShowOne(this, data); target.RpcSetScanner(false); ImportantTextTask importantTextTask = new GameObject("_Player").AddComponent(); importantTextTask.transform.SetParent(base.transform, false); if (!PlayerControl.GameOptions.GhostsDoTasks) { target.ClearTasks(); importantTextTask.Text = DestroyableSingleton.Instance.GetString(StringNames.GhostIgnoreTasks, Array.Empty()); } else { importantTextTask.Text = DestroyableSingleton.Instance.GetString(StringNames.GhostDoTasks, Array.Empty()); } target.myTasks.Insert(0, importantTextTask); } this.MyPhysics.StartCoroutine(this.KillAnimations.Random().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.InstanceExists) { return; } PlayerControl.GameOptions = gameOptions; SaveManager.GameHostOptions = gameOptions; // 调用playercontrol.handleRpc的2 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(); 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.Instance) { DestroyableSingleton.Instance.Chat.AddChat(this, chatText); } if (chatText.IndexOf("who", StringComparison.OrdinalIgnoreCase) >= 0) { DestroyableSingleton.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.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); } //c 角色相关的所有的Rpc调用 public enum RpcCalls : byte { PlayAnimation, CompleteTask, SyncSettings, SetInfected, Exiled, CheckName, SetName, CheckColor, SetColor, SetHat, SetSkin, ReportDeadBody, MurderPlayer, SendChat, TimesImpostor, StartMeeting, SetScanner, SendChatNote, SetPet, SetStartCounter } //c 对应的角色执行对应发过来的Rpc调用 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 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(); this.MurderPlayer(target); return; } case 13: { string chatText = reader.ReadString(); if (DestroyableSingleton.Instance) { DestroyableSingleton.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.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.InstanceExists && this.LastStartCounter < num) { this.LastStartCounter = num; DestroyableSingleton.Instance.SetStartCounter(startCounter); return; } break; } default: return; } } }