You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

187 lines
7.9 KiB

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. /// <summary>
  5. /// Logic block which deals with jumping a character in a direction
  6. /// </summary>
  7. [CreateAssetMenu(menuName = "Major Project/Jump Block")]
  8. [System.Serializable]
  9. public class Jump : LogicBlock
  10. {
  11. [SerializeField]
  12. [Tooltip("Direction to Jump")]
  13. protected Direction direction = Direction.Forward;
  14. [SerializeField]
  15. [Tooltip("Max distance Jump can go")]
  16. protected int Distance = 2;
  17. [SerializeField]
  18. [Tooltip("Max height Jump can go")]
  19. protected int Height = 1;
  20. #region Class Functions
  21. /// <summary>
  22. /// Implementation of BlockLogic, moves the player forward
  23. /// </summary>
  24. /// <param name="player">Player to move</param>
  25. protected override IEnumerator BlockLogic(Character player, float animationTime, bool useBlockDirection = false)
  26. {
  27. player.justMoved = true;
  28. List<Block> jumpBlocks = new List<Block>(); //Blocks to jump forward between
  29. List<Block> bounceBlocks = new List<Block>(); //Blocks to bounce backward across
  30. //Debug.Log("<b>" + player.name + " jumping from " + player.transform.position + "<\b>");
  31. Block endBlock = GetEndBlock(player.CurrentBlock, player.transform, ~player.Ignore);
  32. //Debug.Log("Initial end block: " + endBlock.transform.position);
  33. jumpBlocks.Add(endBlock);
  34. while (endBlock.CurrentPlayer != null && endBlock.CurrentPlayer != player)
  35. {
  36. //Debug.Log("End block occupied! Time to bounce");
  37. Block oldEndBlock = endBlock;
  38. //Debug.Log("oldEndBlock = " + oldEndBlock.transform.position);
  39. endBlock = GetEndBlock(endBlock, player.transform, ~player.Ignore);
  40. //Debug.Log("new endBlock = " + endBlock.transform.position);
  41. if (endBlock == oldEndBlock) //Make sure we're not bouncing on the spot
  42. {
  43. //Debug.Log("We are bouncing in place, stop here");
  44. break;
  45. }
  46. //Debug.Log("Added block to list");
  47. jumpBlocks.Add(endBlock);
  48. }
  49. //If we've ended on a block containing another player, we'll need to bounce backwards until we find an open square
  50. while (endBlock.CurrentPlayer != null && endBlock.CurrentPlayer != player)
  51. {
  52. //Debug.Log("Block at " + endBlock.transform.position + " still occupied, we must bounce back");
  53. Vector3 position = endBlock.position + (Direction.Back.ToVector(player.transform));
  54. endBlock = Block.GetOrCreateBlockAtPosition(position, 1, ~player.Ignore);
  55. //Debug.Log("New endBlock = " + endBlock.transform.position);
  56. bounceBlocks.Add(endBlock);
  57. }
  58. //Jump forward, bouncing across every player
  59. //If there are multi-jumps to be done, they'll happen here
  60. for (int i = 0; i < jumpBlocks.Count - 1; i++)
  61. {
  62. //Debug.Log("Jumping to: " + jumpBlocks[i].transform.position);
  63. yield return player.StartCoroutine(player.AnimateToPosition(jumpBlocks[i].VisualPosition + Vector3.up * 0.5f, Character.Animation.Jump, 0.8f));
  64. }
  65. //If we're at the last queued jump and there are no bouncebacks in the queue, then we've reached an open square, and can officially move here
  66. if (bounceBlocks.Count == 0)
  67. {
  68. //Debug.Log("Final jump to: " + endBlock.transform.position);
  69. yield return player.StartCoroutine(player.MoveToBlock(endBlock, Character.Animation.Jump, animationTime));
  70. }
  71. else //Otherwise, we have to bounce back first
  72. {
  73. yield return player.StartCoroutine(player.AnimateToPosition(jumpBlocks[jumpBlocks.Count - 1].VisualPosition + Vector3.up * 0.5f, Character.Animation.Jump, 0.8f));
  74. for (int i = 0; i < bounceBlocks.Count - 1; i++)
  75. {
  76. //Debug.Log("Bouncing to: " + bounceBlocks[i].transform.position);
  77. yield return player.StartCoroutine(player.AnimateToPosition(bounceBlocks[i].VisualPosition + Vector3.up * 0.5f, Character.Animation.Jump, 0.8f));
  78. }
  79. //Debug.Log("Final bounce to: " + endBlock.transform.position);
  80. yield return player.StartCoroutine(player.MoveToBlock(endBlock, Character.Animation.Jump, animationTime));
  81. }
  82. /*while (endBlock.CurrentPlayer != null && endBlock.CurrentPlayer != player)
  83. {
  84. yield return player.StartCoroutine(player.AnimateToPosition(endBlock.VisualPosition + Vector3.up * 0.5f, Character.Animation.Jump, 0.8f));
  85. endBlock.CurrentPlayer.StartAnimation(Character.Animation.Hit);
  86. endBlock = GetEndBlock(endBlock, player.transform, ~player.Ignore);
  87. }
  88. yield return player.StartCoroutine(player.MoveToBlock(endBlock, Character.Animation.Jump, animationTime));*/
  89. }
  90. /// <summary>
  91. /// Returns the block that the character will endUp on after they use this logic element
  92. /// </summary>
  93. /// <param name="startBlock">block character is on</param>
  94. /// <param name="layerMask">layers to ignore</param>
  95. /// <returns>block which character will finish on after performing this function </returns>
  96. public override Block GetEndBlock(Block startBlock, Transform transform, LayerMask layerMask)
  97. {
  98. //if there is a block infront JumpUp else LongJump
  99. if (Block.isBlockAtPosition(startBlock.position + direction.ToVector(transform) + Vector3.up, 1, layerMask))
  100. return JumpUp(startBlock, transform, layerMask);
  101. else
  102. return JumpLong(startBlock, transform, layerMask);
  103. }
  104. #endregion Class Functions
  105. #region Helper Functions
  106. private Block JumpLong(Block StartBlock, Transform transform, LayerMask layerMask)
  107. {
  108. //setting up variables
  109. Vector3 position; // position wanted
  110. Block retVal = StartBlock; //block we'll actually move to
  111. //Check blocks in front until we hit an obstruction or went the distance
  112. for (int i = 1; i <= Distance; i++)
  113. {
  114. //Next position to MoveTo
  115. position = StartBlock.position + (direction.ToVector(transform) * i);
  116. //if jump is obstructed, stop and go to last known block
  117. if (Block.isBlockAtPosition(position + Vector3.up, 1, layerMask))
  118. break;
  119. retVal = Block.GetOrCreateBlockAtPosition(position, 1, layerMask);
  120. }
  121. return retVal;
  122. }
  123. /// <summary>
  124. /// Jumps up obstacle of specific height. Jumps as high as possible
  125. /// </summary>
  126. /// <param name="direction">Direction of obstacle</param>
  127. /// <param name="height">max height</param>
  128. private Block JumpUp(Block StartBlock, Transform transform, LayerMask layerMask)
  129. {
  130. //setting up variables
  131. Vector3 position; // position wanted
  132. Block hit; //output of block detection
  133. Block retVal = StartBlock; //block we'll actually move to
  134. //Check blocks in going up then move to the heighest walkable one
  135. for (int i = 0; i <= Height; i++)
  136. {
  137. //next position up the tower
  138. position = StartBlock.position + direction.ToVector(transform) + (Vector3.up * i);
  139. //if block is walkable set it to last known position
  140. if (Block.isBlockAtPosition(position, 1, layerMask, out hit) && hit.isWalkable(layerMask))
  141. retVal = hit;
  142. }
  143. return retVal;
  144. }
  145. #endregion Helper Functions
  146. #region Serialisation functions
  147. public override void CopyToken(BlockToken token)
  148. {
  149. base.CopyToken(token);
  150. direction = ((DirectionToken)token).direction;
  151. }
  152. public override BlockToken ToToken(BlockToken token = null)
  153. {
  154. if (token == null)
  155. token = new DirectionToken(this);
  156. DirectionToken retVal = (DirectionToken)base.ToToken(token);
  157. retVal.direction = direction;
  158. return retVal;
  159. }
  160. #endregion Serialisation functions
  161. }