Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections;
- using UnityEngine;
- using UnityEngine.Networking;
- using static Misc;
- using static Player;
- public class Door : Passage, ILockable, IServerInitialisable
- {
- public int initialLock = 0;
- [Header("Visuals")]
- public Sprite[] doorStates;
- [HideInInspector]
- [SyncVar(hook = "SyncDoorProgress")]
- private short openProgress;
- private bool Closed => openProgress == 0;
- private bool Open => openProgress == 100;
- private float unlockTime = 0f;
- private int unlockDifficulty = 0;
- private bool Locked => unlockDifficulty != 0;
- private bool AllowsPassage => !DoorBlocked && !Locked;
- public AudioClip openDoorSound;
- public AudioClip closeDoorSound;
- public AudioClip unlockSound;
- public AudioClip breakingUnlockSound;
- private NetworkAudioSource audioSource;
- private Door DoorTarget => (Door)target;
- //Block Door Logic
- private bool myBlocking;
- [SyncVar(hook = "OnDoorBlockChange")]
- private bool doorBlocked;
- private bool DoorBlocked
- {
- get { return doorBlocked; }
- set { if (value != doorBlocked) { doorBlocked = value; DoorTarget.doorBlocked = value; } }
- }
- private bool myBreaking;
- private bool DoorUnderSiege
- {
- get { return myBreaking; }
- set
- {
- myBreaking = value;
- DoorTarget.myBreaking = value;
- }
- }
- [SyncVar]
- private short doorHealth = 100;
- private short DoorHealth
- {
- get { return doorHealth; }
- set { if (value != doorHealth) { doorHealth = value; DoorTarget.doorHealth = value; } }
- }
- private Coroutine serverBreakRoutine;
- private Coroutine soundCoRoutine;
- private DoorChallenge currentChallenge;
- private bool challengeAvailable = false;
- private DoorChallengeResult? breakerResult;
- private DoorChallengeResult? blockerResult;
- private int challengeID;
- private Action exitChallenge = null;
- private bool Broken => doorHealth == 0;
- public override bool CanBeUsed => base.CanBeUsed && !DoorBlocked;
- private bool CanRepair => Broken && User.InventoryManager.SrvHasObjects(new NailsData(), new WoodPlankData());
- private bool CanBlock => !Broken && Closed;
- private bool CanPick => Locked;
- private bool CanClose => !Closed && !Broken;
- private const float doorRepairTime = 30f;
- void Start()
- {
- audioSource = GetComponent<NetworkAudioSource>();
- if (target != null)
- {
- Debug.Assert(target is Door, "Target for Door must be a door");
- }
- }
- protected override bool Action()
- {
- if (DoorBlocked)
- {
- RpcBreakDoor(User.connectionToClient);
- return true;
- }
- RpcOpenMenu(User.connectionToClient, CanRepair, CanBlock, CanPick, CanClose);
- return true;
- }
- [Server]
- public override bool ChooseAction(Position position)
- {
- if(position == Position.Left && CanRepair)
- {
- Wait(doorRepairTime, OnDoorRepaired);
- return true;
- }
- }
- [TargetRpc]
- private void RpcBreakDoor(NetworkConnection conn)
- {
- LocalPlayer.ProgressMenu.Activate();
- LocalPlayer.PlayerController.RouteInputHook = HandleBreak;
- }
- [TargetRpc]
- private void RpcOpenMenu(NetworkConnection conn, bool canRepair, bool canBlock, bool canPick, bool canClose)
- {
- if (canRepair)
- {
- LocalPlayer.ActionMenu.SetImageAndText(Position.Left, Localisation.Active.RepairTextAM, Localisation.Active.RepairSpriteAM, RepairDoor);
- }
- if (canBlock)
- {
- LocalPlayer.ActionMenu.SetImageAndText(Position.Right, Localisation.Active.BlockTextAM, Localisation.Active.BlockSpriteAM, BlockDoor);
- }
- if (canPick)
- {
- LocalPlayer.ActionMenu.SetImageAndText(Position.Up, Localisation.Active.PickTextAM, Localisation.Active.PickSpriteAM, Unlock);
- }
- else
- {
- LocalPlayer.ActionMenu.SetImageAndText(Position.Up, Localisation.Active.EnterTextAM, Localisation.Active.EnterSpriteAM, Enter);
- }
- if(canClose)
- {
- LocalPlayer.ActionMenu.SetImageAndText(Position.Down, Localisation.Active.CloseTextAM, Localisation.Active.CloseSpriteAM, Close);
- }
- LocalPlayer.ActionMenu.Activate(Leave, () => DoorBlocked);
- }
- public override void Exit() { }
- private void SyncDoorProgress(short progress)
- {
- float p = progress / 100f;
- int idx = Mathf.RoundToInt(p * (doorStates.Length - 1));
- if (idx > doorStates.Length)
- {
- idx = doorStates.Length - 1;
- }
- GetComponent<SpriteRenderer>().sprite = doorStates[idx];
- openProgress = progress;
- }
- private void Enter()
- {
- // Opens the door if necessary, then enters
- if (Open)
- {
- OnDoorOpened();
- }
- else
- {
- audioSource.PlayOneShot(openDoorSound, 1f);
- LocalPlayer.ProgressMenu.RegisterWaitTimeWithProgressing((100 - openProgress) / 100f, Localisation.Active.Opening, OnDoorOpened, Exit, (short progress) => LocalPlayer.UseableManager.Action(NetIdent, PROGRESS_MSG, progress.ToString()), openProgress);
- }
- }
- private void Close()
- {
- LocalPlayer.ProgressMenu.RegisterWaitTimeWithProgressing(
- openProgress / 100f,
- Localisation.Active.Closing,
- OnDoorClosed,
- Exit,
- (short progress) => LocalPlayer.UseableManager.Action(NetIdent, PROGRESS_MSG, (100 - progress).ToString()), 100 - openProgress
- );
- }
- private void RepairDoor()
- {
- audioSource.LoopRandomClips(4f, 7f, AudioPool.Hammer1, AudioPool.Hammer2, AudioPool.Hammer3);
- LocalPlayer.ProgressMenu.RegisterChallengedWaitTime(30f, Localisation.Active.Repairing, 6,
- () => {
- LocalPlayer.InventoryManager.RemoveItem("Nails");
- LocalPlayer.InventoryManager.RemoveItem("Wood Plank");
- LocalPlayer.UseableManager.Action(NetIdent, REPAIR_MSG);
- audioSource.StopLoopRandomClips();
- Leave();
- },
- () =>
- {
- audioSource.StopLoopRandomClips();
- Leave();
- });
- }
- private void OnDoorOpened()
- {
- LocalPlayer.UseableManager.Action(NetIdent, PROGRESS_MSG, "100");
- LocalPlayer.UseableManager.Action(NetIdent, TELEPORT_MSG);
- Leave();
- }
- private void OnDoorClosed()
- {
- LocalPlayer.UseableManager.Action(NetIdent, PROGRESS_MSG, "0");
- Leave();
- }
- protected void Leave()
- {
- base.Leave();
- exitChallenge?.Invoke();
- LocalPlayer.PlayerController.RouteInputHook = null;
- LocalPlayer.ProgressMenu.Deactivate();
- }
- [Server]
- public override void Interconnect(Passage otherDoor)
- {
- base.Interconnect(otherDoor);
- Debug.Assert(target is Door, "Target for Door must be a door");
- audioSource.AddLinkedSource(DoorTarget.audioSource, 1f, true);
- }
- [Server]
- public void Lock(int difficulty)
- {
- if (difficulty == 0)
- {
- unlockDifficulty = 0;
- }
- else
- {
- unlockDifficulty = Mathf.Min(10, unlockDifficulty + difficulty);
- unlockTime += 3f * difficulty;
- }
- if (Linked)
- {
- DoorTarget.unlockDifficulty = unlockDifficulty;
- DoorTarget.unlockTime = unlockTime;
- }
- else
- {
- Debug.Log($"There is an unlinked door in {GetComponentInParent<Room>().gameObject.name} that cannot be locked.");
- }
- }
- [Server]
- public void ServerInit(Room room)
- {
- if (room.LockDoorsInThisRoom != LockType.None)
- {
- if (initialLock == 0)
- {
- Lock(GetRandomDifficulty(room.LockDoorsInThisRoom));
- }
- else
- {
- Lock(initialLock);
- }
- }
- }
- [Client]
- private void Unlock()
- {
- float tmpUnlockTime = unlockTime;
- int tmpUnlockDiff = unlockDifficulty;
- string breakText = Localisation.Active.BreakingLock;
- if (LocalPlayer.InventoryManager.HasObject("Lockpick"))
- {
- tmpUnlockTime *= 0.5f;
- tmpUnlockDiff = Mathf.Max(1, tmpUnlockDiff - 3);
- breakText = Localisation.Active.PickingLock;
- audioSource.PlayAndLoop(unlockSound, 1f);
- }
- else
- {
- audioSource.PlayAndLoop(breakingUnlockSound, 1f);
- }
- LocalPlayer.ProgressMenu.RegisterChallengedWaitTime(tmpUnlockTime, breakText, tmpUnlockDiff, () =>
- {
- audioSource.FadeOut(0.5f);
- LocalPlayer.UseableManager.Action(NetIdent, UNLOCK_MSG);
- Leave();
- }, () =>
- {
- audioSource.FadeOut(0.5f);
- Leave();
- });
- }
- public bool CheckLockConditionsOk()
- {
- if (!Closed)
- {
- RpcCloseDoorsFirst(User.connectionToClient);
- return false;
- }
- return true;
- }
- [TargetRpc]
- private void RpcCloseDoorsFirst(NetworkConnection conn)
- {
- LocalPlayer.PlayerVisuals.CreateTextEffect(Localisation.Active.CloseDoorsFirst);
- }
- private void BlockDoor()
- {
- myBlocking = true;
- LocalPlayer.ProgressMenu.Activate();
- LocalPlayer.PlayerController.RouteInputHook = HandleBlock;
- LocalPlayer.UseableManager.Action(NetIdent, START_BLOCKING);
- }
- private void StopBlockDoor()
- {
- myBlocking = false;
- LocalPlayer.UseableManager.Action(NetIdent, STOP_BLOCKING);
- }
- private void HandleBlock()
- {
- if (Input.GetKeyDown(KeyboardConfiguration.Use))
- {
- StopBlockDoor();
- Leave();
- return;
- }
- if (Broken || !myBlocking)
- {
- Leave();
- return;
- }
- HandleProgressAndChallenges(false);
- }
- private void HandleBreak()
- {
- if (Input.GetKeyDown(KeyboardConfiguration.Use))
- {
- LocalPlayer.UseableManager.Action(NetIdent, STOP_BREAKING);
- Leave();
- return;
- }
- if (Broken || !DoorBlocked)
- {
- Leave();
- return;
- }
- HandleProgressAndChallenges(true);
- }
- private void OnDoorBlockChange(bool value)
- {
- myBlocking = value;
- DoorTarget.myBlocking = value;
- DoorBlocked = value;
- if(!value)
- {
- Leave();
- }
- }
- private void HandleProgressAndChallenges(bool breaker)
- {
- LocalPlayer.ProgressMenu.SetProgress(Convert.ToSingle(DoorHealth) / 100);
- if (breaker)
- {
- LocalPlayer.ProgressMenu.SetStatusText(Localisation.Active.Breaking);
- }
- else
- {
- LocalPlayer.ProgressMenu.SetStatusText(Localisation.Active.Blocking);
- }
- if (challengeAvailable)
- {
- challengeAvailable = false;
- LocalPlayer.ProgressMenu.Deactivate();
- LocalPlayer.ProgressMenu.ChallengeSystem.RequestSpecificChallenge(
- currentChallenge.challengeType,
- currentChallenge.difficulty,
- (result) =>
- {
- SendBreakBlockResult(result, breaker, currentChallenge.id);
- LocalPlayer.ProgressMenu.Activate();
- exitChallenge = null;
- if (breaker)
- {
- LocalPlayer.PlayerController.RouteInputHook = HandleBreak;
- }
- else
- {
- LocalPlayer.PlayerController.RouteInputHook = HandleBlock;
- }
- },
- out exitChallenge);
- }
- }
- private void SendBreakBlockResult(ChallengeResult result, bool breaking, int id)
- {
- if (DoorBlocked)
- {
- LocalPlayer.UseableManager.Action(NetIdent, SEND_RESULT, Misc.ConvertObjectsToString(breaking.ToString(), id.ToString(), result.success.ToString()));
- LocalPlayer.ProgressMenu.Activate();
- }
- }
- public void Action(Player player, byte action, string message)
- {
- switch (action)
- {
- case TELEPORT_MSG:
- if (AllowsPassage)
- {
- RpcTeleportUser(player.NetworkIdentity, Misc.ConvertObjectsToString(target.spawner.position.x, target.spawner.position.y, target.spawner.position.z));
- }
- break;
- case PROGRESS_MSG:
- if (AllowsPassage && !Broken)
- {
- short progress = short.Parse(message);
- SetProgress(progress);
- }
- break;
- case UNLOCK_MSG:
- unlockDifficulty = 0;
- unlockTime = 0f;
- DoorTarget.unlockDifficulty = unlockDifficulty;
- DoorTarget.unlockTime = unlockTime;
- break;
- case START_BREAKING:
- SrvStartBreaking();
- break;
- case STOP_BREAKING:
- SrvStopBreaking();
- break;
- case START_BLOCKING:
- SrvBlockDoor();
- break;
- case STOP_BLOCKING:
- SrvStopBlockDoor();
- break;
- case SEND_RESULT:
- // breaking, id, success
- string[] messageParts = Misc.ConvertStringToStringArr(message);
- bool breakingRes = bool.Parse(messageParts[0]);
- int idRes = int.Parse(messageParts[1]);
- bool successRes = bool.Parse(messageParts[2]);
- DoorChallengeResult res = new DoorChallengeResult()
- {
- id = idRes,
- success = successRes
- };
- SrvSendResult(breakingRes, res);
- break;
- case REPAIR_MSG:
- DoorHealth = 100;
- break;
- }
- }
- [Server]
- private void SetProgress(short progress)
- {
- openProgress = progress;
- DoorTarget.openProgress = progress;
- if(progress == 0)
- {
- audioSource.PlayOneShot(closeDoorSound, 1f);
- }
- }
- [Server]
- private void SrvBreakDoor()
- {
- DoorHealth = 0;
- audioSource.PlayOneShot(AudioPool.BreakdownDoor, 1f);
- DoorUnderSiege = false;
- unlockDifficulty = 0;
- DoorTarget.unlockDifficulty = 0;
- unlockTime = 0;
- DoorTarget.unlockTime = 0;
- DoorBlocked = false;
- SetProgress(100);
- }
- [Server]
- private void SrvBlockDoor()
- {
- if (!Broken)
- {
- DoorBlocked = true;
- }
- }
- [Server]
- private void SrvStopBlockDoor()
- {
- DoorBlocked = false;
- if(DoorUnderSiege)
- {
- SrvBreakDoor();
- }
- }
- [Server]
- private void SrvStartBreaking()
- {
- if (DoorBlocked)
- {
- DoorUnderSiege = true;
- serverBreakRoutine = StartCoroutine(BreakDoor());
- soundCoRoutine = StartCoroutine(CauseBreakingSounds());
- }
- }
- [Server]
- private void SrvStopBreaking()
- {
- DoorUnderSiege = false;
- StopCoroutine(serverBreakRoutine);
- StopCoroutine(soundCoRoutine);
- }
- [Server]
- private void SrvSendResult(bool breaker, DoorChallengeResult result)
- {
- if (breaker)
- {
- breakerResult = result;
- DoorTarget.breakerResult = result;
- }
- else
- {
- blockerResult = result;
- DoorTarget.blockerResult = result;
- }
- }
- [ClientRpc]
- private void RpcSetChallenge(DoorChallenge challenge)
- {
- currentChallenge = challenge;
- DoorTarget.currentChallenge = challenge;
- challengeAvailable = true;
- DoorTarget.challengeAvailable = true;
- }
- [ClientRpc]
- private void RpcShake()
- {
- LocalPlayer.ProgressMenu.Shake();
- }
- [ClientRpc]
- private void RpcShakeDoor()
- {
- StartCoroutine(ShakeDoor());
- }
- [Client]
- private IEnumerator ShakeDoor()
- {
- float animationDuration = 0.1f;
- float pause = GlobalVars.GetNextFloat(0.1f, 0.3f);
- for(int i = 0; i< 2; i++)
- {
- float passedTime = 0f;
- while(passedTime < animationDuration)
- {
- passedTime += Time.deltaTime;
- float progress = Math.Min(passedTime / animationDuration, 1f);
- float size = Mathf.Lerp(1, 1.05f, progress);
- transform.localScale = new Vector3(size, size, size);
- yield return null;
- }
- passedTime = 0f;
- while (passedTime < animationDuration)
- {
- passedTime += Time.deltaTime;
- float progress = Math.Min(passedTime / animationDuration, 1f);
- float size = Mathf.Lerp(1.05f, 1f, progress);
- transform.localScale = new Vector3(size, size, size);
- yield return null;
- }
- yield return new WaitForSeconds(pause);
- }
- }
- [Server]
- private IEnumerator BreakDoor()
- {
- byte currentDifficulty = 5;
- while (DoorUnderSiege)
- {
- blockerResult = null;
- breakerResult = null;
- yield return new WaitForSeconds(GlobalVars.Random.Next(2, 4));
- byte chosenChallenge = Convert.ToByte(GlobalVars.Random.Next(ChallengeSystem.NUMBER_OF_CHALLENGES));
- RpcSetChallenge(CreateChallenge(currentDifficulty, chosenChallenge, out challengeID));
- // Players have four seconds to solve the challenge
- yield return new WaitForSeconds(4);
- if (!breakerResult.HasValue || breakerResult.Value.id != challengeID)
- {
- DoorHealth = 100;
- }
- else if (!blockerResult.HasValue || blockerResult.Value.id != challengeID)
- {
- SrvBreakDoor();
- yield break;
- }
- else
- {
- float baseDamage = 20f;
- if (breakerResult.Value.success)
- {
- baseDamage *= 2f;
- }
- if (blockerResult.Value.success)
- {
- baseDamage *= 0.5f;
- }
- DoorHealth -= Convert.ToInt16(Math.Ceiling(baseDamage));
- if (DoorHealth <= 0)
- {
- // Door is broken
- SrvBreakDoor();
- yield break;
- }
- if (breakerResult.Value.success && blockerResult.Value.success)
- {
- // Both succeeded, increasing difficulty
- currentDifficulty = (byte)Math.Min(10, currentDifficulty + 1);
- }
- if (!breakerResult.Value.success && !blockerResult.Value.success)
- {
- // Both failed, decrease diff
- currentDifficulty = (byte)Math.Max(5, currentDifficulty - 1);
- }
- }
- }
- }
- [Server]
- private IEnumerator CauseBreakingSounds()
- {
- AudioClip[] clips = new AudioClip[3]
- {
- AudioPool.DoorHammer01,
- AudioPool.DoorHammer02,
- AudioPool.DoorHammer03
- };
- while (DoorUnderSiege)
- {
- audioSource.PlayOneShot(clips[GlobalVars.Random.Next(0, clips.Length)], 1f);
- RpcShake();
- RpcShakeDoor();
- DoorTarget.RpcShakeDoor();
- yield return new WaitForSeconds(GlobalVars.GetNextFloat(3f, 4f));
- }
- }
- [Server]
- private DoorChallenge CreateChallenge(byte difficulty, byte type, out int id)
- {
- DoorChallenge challenge = new DoorChallenge
- {
- id = GlobalVars.Random.Next(),
- difficulty = difficulty,
- challengeType = type
- };
- id = challenge.id;
- return challenge;
- }
- private struct DoorChallenge
- {
- public int id;
- public byte difficulty;
- public byte challengeType;
- }
- private struct DoorChallengeResult
- {
- public int id;
- public bool success;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment