public override WormAIBaseState Update() { switch (subState) { case SubState.GOING_TO_ENTRY: //Position head below entry point currentX = bb.GetJumpXGivenY(-WormBlackboard.NAVMESH_LAYER_HEIGHT, false); Vector3 startPosition = bb.GetJumpPositionGivenY(-WormBlackboard.NAVMESH_LAYER_HEIGHT, false); headTrf.position = startPosition; lastPosition = startPosition; head.SetVisible(true); origin.WormEnterExit(); subState = SubState.JUMPING; break; case SubState.JUMPING: //While not again below underground navmesh layer advance currentX += Time.deltaTime * bb.spawnSpeed; lastPosition = headTrf.position; headTrf.position = bb.GetJumpPositionGivenX(currentX); headTrf.LookAt(headTrf.position + (headTrf.position - lastPosition), headTrf.up); if (lastPosition.y > headTrf.position.y && rotation < 90f) { if (!highestPointReached) { highestPointReached = true; } float angle = 30 * Time.deltaTime; headTrf.Rotate(new Vector3(0, 0, angle)); rotation += angle; } if (!destinyInRange) { float distanceToDestiny = (headTrf.position - destiny.transform.position).magnitude; if (distanceToDestiny <= destinyInRangeDistance || (headTrf.position.y < destiny.transform.position.y && currentX >= 0)) //Safety check. When jump is too fast distance can never be less than range distance { destinyInRange = true; AttackActions(); destiny.WormAboveAttackStart(); } } if (headTrf.position.y < -WormBlackboard.NAVMESH_LAYER_HEIGHT) { SetHeadUnderground(); subState = SubState.EXITING; } break; case SubState.EXITING: currentX += Time.deltaTime * bb.spawnSpeed; lastPosition = headTrf.position; headTrf.position = bb.GetJumpPositionGivenX(currentX); headTrf.LookAt(headTrf.position + (headTrf.position - lastPosition)); if (bb.tailReachedMilestone) { Vector3 pos = headTrf.position; pos.y = -WormBlackboard.NAVMESH_LAYER_HEIGHT; headTrf.position = pos; return(head.wanderingState); } break; default: break; } return(null); }
public override WormAIBaseState Update() { switch (subState) { case SubState.WAITING: if (elapsedTime >= bb.WanderingSettingsPhase.initialWaitTime) { head.agent.enabled = false; currentWP = route.wayPoints[WPIndex].transform.position; nextWP = route.wayPoints[WPIndex + 1].transform.position; currentWPUG = currentWP - bb.navMeshLayersDistance; nextWPUG = nextWP - bb.navMeshLayersDistance; headTrf.position = currentWPUG; headTrf.LookAt(nextWPUG, Vector3.up); bb.CalculateWorldEnterBezierPoints(headTrf); head.SetVisible(true); //Rotate head Vector3 headUp = currentWPUG - nextWPUG; headTrf.LookAt(currentWP, headUp); t = 0; HexagonController hexagon = route.wayPoints[WPIndex].GetComponent <HexagonController>(); hexagon.WormEnterExit(); EnterExitActions(); head.animator.SetBool("MouthOpen", true); bb.isHeadOverground = true; bb.applySinMovement = true; subState = SubState.ENTERING; } else { elapsedTime += Time.deltaTime; } break; case SubState.ENTERING: if (t <= 2) { shouldMove = Time.deltaTime * bb.WanderingSettingsPhase.wanderingSpeed; actuallyMoved = 0; lastPosition = headTrf.position; Vector3 newPos = Vector3.zero; while (actuallyMoved < shouldMove && t <= 2) { newPos = bb.GetEnterCurvePosition(currentWPUG, nextWP, t); actuallyMoved = (newPos - lastPosition).magnitude; t += Time.deltaTime / duration; } headTrf.position = newPos; headTrf.LookAt(headTrf.position + (headTrf.position - lastPosition)); } else { ++WPIndex; currentWP = route.wayPoints[WPIndex].transform.position; head.agent.areaMask = WormBlackboard.NAVMESH_FLOOR_LAYER; head.agent.enabled = true; head.agent.speed = bb.WanderingSettingsPhase.wanderingSpeed; head.agent.SetDestination(currentWP); head.animator.SetBool("MouthOpen", false); bb.meteorInmediate = true; elapsedTime = 0; subState = SubState.FOLLOWING_PATH; } break; case SubState.FOLLOWING_PATH: if (bb.AboveAttackSettingsPhase.active && head.CheckPlayerInSight(bb.AboveAttackSettingsPhase.exposureMinHexagons, bb.AboveAttackSettingsPhase.exposureMaxHexagons, false)) { bb.aboveAttackCurrentExposureTime += Time.deltaTime; if (!angryEyes) { angryEyes = true; head.WatchingPlayer(); } } else { if (angryEyes) { angryEyes = false; head.NotWatchingPlayer(); } } if (bb.attacksEnabled && bb.AboveAttackSettingsPhase.active && bb.aboveAttackCurrentExposureTime >= bb.AboveAttackSettingsPhase.exposureTimeNeeded && bb.aboveAttackCurrentCooldownTime >= bb.AboveAttackSettingsPhase.cooldownTime && head.CheckPlayerInSight(bb.AboveAttackSettingsPhase.attackMinHexagons, bb.AboveAttackSettingsPhase.attackMaxHexagons, true)) { if (bb.playerInSight != null) { HexagonController destiny = bb.playerInSight.GetNearestHexagon(); if (destiny != null && destiny.isWormSelectable) { if (angryEyes) { angryEyes = false; head.NotWatchingPlayer(); } return(head.aboveAttackState); } } } //Not reached next waypoint if (elapsedTime >= 6f) { head.agent.enabled = false; destiny = GetExitHexagon(); bb.CalculateParabola(headTrf.position, destiny.transform.position); speed = (headTrf.position - destiny.transform.position).magnitude / bb.headDestroyedJumpDuration; //Calculate start point and prior point currentX = bb.GetJumpXGivenY(0, false); Vector3 startPosition = bb.GetJumpPositionGivenY(0, false); headTrf.position = startPosition; lastPosition = bb.GetJumpPositionGivenX(currentX); float fakeNextX = currentX + Time.deltaTime * 2; Vector3 nextPosition = bb.GetJumpPositionGivenX(fakeNextX); headTrf.rotation = Quaternion.LookRotation(nextPosition - startPosition, headTrf.up); subState = SubState.JUMPING; } else { elapsedTime += Time.deltaTime; if (!head.agent.hasPath || (head.agent.hasPath && head.agent.remainingDistance <= 0.25)) { if (WPIndex == route.wayPoints.Length - 2) { head.agent.enabled = false; currentWP = route.wayPoints[WPIndex].transform.position; nextWP = route.wayPoints[WPIndex + 1].transform.position; currentWPUG = currentWP - bb.navMeshLayersDistance; nextWPUG = nextWP - bb.navMeshLayersDistance; headTrf.LookAt(nextWP, Vector3.up); bb.CalculateWorldExitBezierPoints(headTrf); t = 0; HexagonController hexagon = route.wayPoints[WPIndex + 1].GetComponent <HexagonController>(); hexagon.WormEnterExit(); if (angryEyes) { angryEyes = false; head.NotWatchingPlayer(); } head.animator.SetBool("MouthOpen", true); bb.meteorInmediate = false; subState = SubState.EXITING; } else { elapsedTime = 0; ++WPIndex; currentWP = route.wayPoints[WPIndex].transform.position; head.agent.SetDestination(currentWP); } } } break; case SubState.EXITING: if (t <= 2) { shouldMove = Time.deltaTime * bb.WanderingSettingsPhase.wanderingSpeed; actuallyMoved = 0; lastPosition = headTrf.position; Vector3 newPos = Vector3.zero; if (t >= 1.6f && !exitRumble) { exitRumble = true; EnterExitActions(); } while (actuallyMoved < shouldMove && t <= 2) { newPos = bb.GetExitCurvePosition(currentWP, nextWPUG, t); actuallyMoved = (newPos - lastPosition).magnitude; t += Time.deltaTime / duration; } headTrf.position = newPos; headTrf.LookAt(headTrf.position + (headTrf.position - lastPosition)); } else { SetUndergroundDirection(); SetHeadUnderground(); head.animator.SetBool("MouthOpen", false); subState = SubState.WAITING_FOR_TAIL; } break; case SubState.WAITING_FOR_TAIL: //move head until tail is undeground if (!bb.tailReachedMilestone) { MoveUndergroundDirection(); } else { bb.applySinMovement = false; if (bb.shouldMeteorBeTriggedAfterWandering) { return(head.meteorAttackState); } //If some random condition attack, else new wandering state else if (bb.attacksEnabled && bb.BelowAttackSettingsPhase.active && Random.Range(0f, 1f) <= bb.BelowAttackSettingsPhase.chancesOfBelowAttackAfterWandering / 100) { return(head.belowAttackState); } else { SetInitialState(); } } break; //Failsafe exit case SubState.JUMPING: //While not again below underground navmesh layer advance currentX += Time.deltaTime * speed; lastPosition = headTrf.position; headTrf.position = bb.GetJumpPositionGivenX(currentX); headTrf.LookAt(headTrf.position + (headTrf.position - lastPosition), headTrf.up); if (!destinyInRange) { float distanceToDestiny = (headTrf.position - destiny.transform.position).magnitude; if (distanceToDestiny <= destinyInRangeDistance || headTrf.position.y < destiny.transform.position.y) //Safety check. When jump is too fast distance can never be less than range distance { destinyInRange = true; JumpExitActions(); destiny.WormEnterExit(); } } if (headTrf.position.y < -WormBlackboard.NAVMESH_LAYER_HEIGHT) { SetHeadUnderground(); head.animator.SetBool("MouthOpen", false); subState = SubState.JUMP_EXITING; } break; case SubState.JUMP_EXITING: currentX += Time.deltaTime * speed; lastPosition = headTrf.position; headTrf.position = bb.GetJumpPositionGivenX(currentX); headTrf.LookAt(headTrf.position + (headTrf.position - lastPosition)); if (bb.tailReachedMilestone) { Vector3 pos = headTrf.position; pos.y = -WormBlackboard.NAVMESH_LAYER_HEIGHT; headTrf.position = pos; return(head.wanderingState); } break; default: break; } return(null); }
public override WormAIBaseState Update() { switch (subState) { case SubState.KNOCKED_OUT: if (elapsedTime >= bb.HealthSettingsPhase.knockOutTime) { //Restore head.recoverSoundFx.Play(); head.ResetPhase(); destiny = GetExitHexagon(); bb.CalculateParabola(headTrf.position, destiny.transform.position); speed = (headTrf.position - destiny.transform.position).magnitude / bb.headDestroyedJumpDuration; //Calculate start point and prior point currentX = bb.GetJumpXGivenY(0, false); Vector3 startPosition = bb.GetJumpPositionGivenY(0, false); headTrf.position = startPosition; lastPosition = bb.GetJumpPositionGivenX(currentX); float fakeNextX = currentX + Time.deltaTime * 2; Vector3 nextPosition = bb.GetJumpPositionGivenX(fakeNextX); initialRotation = Quaternion.LookRotation(nextPosition - startPosition, headTrf.up); head.animator.SetBool("Stunned", false); head.animator.SetBool("MouthOpen", true); elapsedTime = 0f; head.SetInvulnerable(); subState = SubState.MOVING_HEAD; } else { if (elapsedTime >= 3f && !knockOutTutorialTriggered) { knockOutTutorialTriggered = true; TutorialEventInfo.eventInfo.type = TutorialManager.Type.HIT_BOSS_HEAD; rsc.eventMng.TriggerEvent(EventManager.EventType.SHOW_TUTORIAL, TutorialEventInfo.eventInfo); } elapsedTime += Time.deltaTime; } break; case SubState.MOVING_HEAD: headTrf.rotation = Quaternion.RotateTowards(headTrf.rotation, initialRotation, bb.headDestroyedLookRotationSpeed * Time.deltaTime); if (elapsedTime >= bb.headDestoryedBodyWaitTime) { subState = SubState.JUMPING; } else { elapsedTime += Time.deltaTime; } break; case SubState.JUMPING: //While not again below underground navmesh layer advance currentX += Time.deltaTime * speed; lastPosition = headTrf.position; headTrf.position = bb.GetJumpPositionGivenX(currentX); headTrf.LookAt(headTrf.position + (headTrf.position - lastPosition), headTrf.up); headTrf.Rotate(new Vector3(0, 0, bb.headDestroyedRotationSpeed * Time.deltaTime)); if (!destinyInRange) { float distanceToDestiny = (headTrf.position - destiny.transform.position).magnitude; if (distanceToDestiny <= destinyInRangeDistance || headTrf.position.y < destiny.transform.position.y) //Safety check. When jump is too fast distance can never be less than range distance { destinyInRange = true; JumpExitActions(); destiny.WormEnterExit(); } } if (headTrf.position.y < -WormBlackboard.NAVMESH_LAYER_HEIGHT) { SetHeadUnderground(); head.animator.SetBool("MouthOpen", false); subState = SubState.EXITING; } break; case SubState.EXITING: currentX += Time.deltaTime * speed; lastPosition = headTrf.position; headTrf.position = bb.GetJumpPositionGivenX(currentX); headTrf.LookAt(headTrf.position + (headTrf.position - lastPosition)); if (bb.tailReachedMilestone) { Vector3 pos = headTrf.position; pos.y = -WormBlackboard.NAVMESH_LAYER_HEIGHT; headTrf.position = pos; return(head.wanderingState); } break; default: break; } return(null); }
public override WormAIBaseState Update() { switch (subState) { case SubState.WAITING: if (elapsedTime >= bb.BelowAttackSettingsPhase.initialWaitTime) { GameObject playerGO = rsc.enemyMng.SelectPlayerRandom(); if (playerGO != null) { PlayerController player = playerGO.GetComponent <PlayerController>(); origin = player.GetNearestHexagon(); if (origin != null) { if (!origin.isWormSelectable) { return(head.wanderingState); } head.animator.SetBool("Bite", true); destiny = GetHexagonFacingCenter(origin, destinyHexagonsDistance); bb.CalculateParabola(origin.transform.position, destiny.transform.position); head.agent.enabled = false; rotation = 0f; destinyInRange = false; } else { return(head.wanderingState); } } else { return(head.wanderingState); } origin.WormBelowAttackWarning(bb.BelowAttackSettingsPhase.adjacentDamagingCells); elapsedTime = 0f; head.attackWarningSoundFx.Play(); subState = SubState.WARNING_PLAYER; } else { elapsedTime += Time.deltaTime; } break; case SubState.WARNING_PLAYER: if (elapsedTime >= bb.BelowAttackSettingsPhase.warningTime) { //Position head below entry point currentX = bb.GetJumpXGivenY(-WormBlackboard.NAVMESH_LAYER_HEIGHT, false); Vector3 startPosition = bb.GetJumpPositionGivenY(-WormBlackboard.NAVMESH_LAYER_HEIGHT, false); headTrf.position = startPosition; lastPosition = startPosition; head.SetVisible(true); origin.WormBelowAttackStart(); AttackActions(); bb.isHeadOverground = true; subState = SubState.JUMPING; } else { elapsedTime += Time.deltaTime; } break; case SubState.JUMPING: //While not again below underground navmesh layer advance currentX += Time.deltaTime * bb.BelowAttackSettingsPhase.jumpSpeed; lastPosition = headTrf.position; headTrf.position = bb.GetJumpPositionGivenX(currentX); headTrf.LookAt(headTrf.position + (headTrf.position - lastPosition), headTrf.up); float angle = bb.BelowAttackSettingsPhase.rotationSpeed * Time.deltaTime; headTrf.Rotate(new Vector3(0, 0, angle)); rotation += angle; if (!destinyInRange) { float distanceToDestiny = (headTrf.position - destiny.transform.position).magnitude; if (distanceToDestiny <= destinyInRangeDistance || (headTrf.position.y < destiny.transform.position.y && currentX >= 0)) //Safety check. When jump is too fast distance can never be less than range distance { destinyInRange = true; JumpExitActions(); destiny.WormEnterExit(); } } if (headTrf.position.y < -WormBlackboard.NAVMESH_LAYER_HEIGHT) { bb.isHeadOverground = false; bb.tailReachedMilestone = false; bb.FlagCurrentWaypointAsMilestone(); head.SetVisible(false); subState = SubState.EXITING; } break; case SubState.EXITING: currentX += Time.deltaTime * bb.BelowAttackSettingsPhase.jumpSpeed; lastPosition = headTrf.position; headTrf.position = bb.GetJumpPositionGivenX(currentX); headTrf.LookAt(headTrf.position + (headTrf.position - lastPosition)); if (bb.tailReachedMilestone) { //Debug.Break(); Vector3 pos = headTrf.position; pos.y = -WormBlackboard.NAVMESH_LAYER_HEIGHT; headTrf.position = pos; return(head.wanderingState); } break; default: break; } return(null); }
public override WormAIBaseState Update() { switch (subState) { //Wait for head Fx and animation case SubState.WAITING_HEAD: if (elapsedTime >= bb.headDestroyedWaitTime) { if (!shouldTriggerMeteor) { destiny = GetExitHexagon(); bb.CalculateParabola(headTrf.position, destiny.transform.position); speed = (headTrf.position - destiny.transform.position).magnitude / bb.headDestroyedJumpDuration; //Calculate start point and prior point currentX = bb.GetJumpXGivenY(0, false); Vector3 startPosition = bb.GetJumpPositionGivenY(0, false); headTrf.position = startPosition; lastPosition = bb.GetJumpPositionGivenX(currentX); float fakeNextX = currentX + Time.deltaTime * 2; Vector3 nextPosition = bb.GetJumpPositionGivenX(fakeNextX); initialRotation = Quaternion.LookRotation(nextPosition - startPosition, headTrf.up); } head.animator.SetBool("Hit", false); bb.ConsolidateBodyParts(); subState = SubState.WAITING_BODY; elapsedTime = 0f; } else { elapsedTime += Time.deltaTime; } break; //Wait for body parts destruction case SubState.WAITING_BODY: if (bb.wormCurrentPhase < bb.wormMaxPhases - 1 && !shouldTriggerMeteor) { headTrf.rotation = Quaternion.RotateTowards(headTrf.rotation, initialRotation, bb.headDestroyedLookRotationSpeed * Time.deltaTime); } if (elapsedTime >= bb.headDestoryedBodyWaitTime) { if (bb.wormCurrentPhase == bb.wormMaxPhases - 1) { return(head.dyingState); } else { head.StartNewPhase(); head.SetMaterial(rsc.coloredObjectsMng.GetWormHeadMaterial(bb.headCurrentChargeLevel)); //rsc.eventMng.TriggerEvent(EventManager.EventType.WORM_HEAD_ACTIVATED, EventInfo.emptyInfo); if (shouldTriggerMeteor) { bb.meteorInmediate = true; return(head.meteorAttackState); } else { head.animator.SetBool("MouthOpen", true); subState = SubState.JUMPING; } } } else { elapsedTime += Time.deltaTime; } break; case SubState.JUMPING: //While not again below underground navmesh layer advance currentX += Time.deltaTime * speed; lastPosition = headTrf.position; headTrf.position = bb.GetJumpPositionGivenX(currentX); headTrf.LookAt(headTrf.position + (headTrf.position - lastPosition), headTrf.up); headTrf.Rotate(new Vector3(0, 0, bb.headDestroyedRotationSpeed * Time.deltaTime)); if (!destinyInRange) { float distanceToDestiny = (headTrf.position - destiny.transform.position).magnitude; if (distanceToDestiny <= destinyInRangeDistance || headTrf.position.y < destiny.transform.position.y) //Safety check. When jump is too fast distance can never be less than range distance { destinyInRange = true; JumpExitActions(); destiny.WormEnterExit(); } } if (headTrf.position.y < -WormBlackboard.NAVMESH_LAYER_HEIGHT) { SetHeadUnderground(); head.animator.SetBool("MouthOpen", false); subState = SubState.EXITING; } break; case SubState.EXITING: currentX += Time.deltaTime * speed; lastPosition = headTrf.position; headTrf.position = bb.GetJumpPositionGivenX(currentX); headTrf.LookAt(headTrf.position + (headTrf.position - lastPosition)); if (bb.tailReachedMilestone) { Vector3 pos = headTrf.position; pos.y = -WormBlackboard.NAVMESH_LAYER_HEIGHT; headTrf.position = pos; return(head.wanderingState); } break; default: break; } return(null); }
public override WormAIBaseState Update() { switch (subState) { //Underground path case SubState.UNDERGROUND_START: GameObject playerGO = rsc.enemyMng.SelectPlayerRandom(); if (playerGO != null) { PlayerController player = playerGO.GetComponent <PlayerController>(); origin = player.GetNearestHexagon(); if (origin != null) { if (!origin.isWormSelectable) { return(head.wanderingState); } destiny = GetHexagonFacingCenter(origin, 2); bb.CalculateParabola(origin.transform.position, destiny.transform.position); head.agent.enabled = false; } else { return(head.wanderingState); } } else { return(head.wanderingState); } origin.WormEnterExit(); elapsedTime = 0f; head.attackWarningSoundFx.Play(); subState = SubState.WARNING_PLAYER; break; case SubState.WARNING_PLAYER: if (elapsedTime >= bb.MeteorAttackSettingsPhase.warningTime) { //Position head below entry point currentX = bb.GetJumpXGivenY(-WormBlackboard.NAVMESH_LAYER_HEIGHT, false); Vector3 startPosition = bb.GetJumpPositionGivenY(-WormBlackboard.NAVMESH_LAYER_HEIGHT, false); headTrf.position = startPosition; lastPosition = startPosition; head.SetVisible(true); elapsedTime = 0f; bb.isHeadOverground = true; subState = SubState.HEAD_EXIT; } else { elapsedTime += Time.deltaTime; } break; case SubState.HEAD_EXIT: if (headTrf.position.y < 2) { currentX += Time.deltaTime * bb.MeteorAttackSettingsPhase.enterHeadSpeed; lastPosition = headTrf.position; headTrf.position = bb.GetJumpPositionGivenX(currentX); headTrf.LookAt(headTrf.position + (headTrf.position - lastPosition), headTrf.up); elapsedTime += Time.deltaTime; } else { elapsedTime += bb.MeteorAttackSettingsPhase.warningTime; subState = SubState.OPENING_MOUTH; } break; //Overground path case SubState.OVERGROUND_START: destiny = GetExitHexagon(); bb.CalculateParabola(headTrf.position, destiny.transform.position); subState = SubState.OPENING_MOUTH; break; //Common path case SubState.OPENING_MOUTH: if (elapsedTime >= 1.5f) { elapsedTime = 0; //head.fireSpray.transform.position = head.headModel.transform.position + (Vector3.up * 0.5f); //head.fireSpray.transform.LookAt(head.fireSpray.transform.position + Vector3.up, head.transform.up); //head.fireSpray.Play(); subState = SubState.SHOOTING; } else { elapsedTime += Time.deltaTime; } break; case SubState.SHOOTING: if (totalShots < bb.MeteorAttackSettingsPhase.numberOfThrownMeteors) { if (elapsedTime <= 0) { MeteorController meteor = rsc.poolMng.meteorPool.GetObject(); meteor.transform.position = head.meteorSpawnPoint.position; meteor.GoUp(bb.MeteorAttackSettingsPhase.speedOfThrownMeteors); rsc.rumbleMng.Rumble(0, 0.15f, 0, 0.6f); rsc.camerasMng.PlayEffect(0, 0.1f, 0.3f); ++totalShots; elapsedTime = timeBetweenShots; } else { elapsedTime -= Time.deltaTime; } } else { speed = (headTrf.position - destiny.transform.position).magnitude / bb.MeteorAttackSettingsPhase.jumpDuration; //Calculate start point and prior point currentX = bb.GetJumpXGivenY(headTrf.position.y, false); Vector3 startPosition = bb.GetJumpPositionGivenY(headTrf.position.y, false); headTrf.position = startPosition; lastPosition = bb.GetJumpPositionGivenX(currentX); float fakeNextX = currentX + Time.deltaTime * 2; Vector3 nextPosition = bb.GetJumpPositionGivenX(fakeNextX); initialRotation = Quaternion.LookRotation(nextPosition - startPosition, headTrf.up); head.fireSpray.Stop(); elapsedTime = 0; if (underground) { head.animator.SetBool("MouthOpen", false); } else { head.animator.SetBool("MouthOpenTrans", false); head.animator.SetBool("Jump", true); } subState = SubState.CLOSING_MOUTH; } break; case SubState.CLOSING_MOUTH: headTrf.rotation = Quaternion.RotateTowards(headTrf.rotation, initialRotation, bb.headDestroyedLookRotationSpeed * Time.deltaTime); if (elapsedTime >= 1) { elapsedTime = 0; subState = SubState.JUMPING; head.animator.SetBool("Jump", false); } else { elapsedTime += Time.deltaTime; } break; case SubState.JUMPING: //While not again below underground navmesh layer advance currentX += Time.deltaTime * speed; lastPosition = headTrf.position; headTrf.position = bb.GetJumpPositionGivenX(currentX); headTrf.LookAt(headTrf.position + (headTrf.position - lastPosition), headTrf.up); headTrf.Rotate(new Vector3(0, 0, bb.MeteorAttackSettingsPhase.rotationSpeed * Time.deltaTime)); if (!destinyInRange) { float distanceToDestiny = (headTrf.position - destiny.transform.position).magnitude; if (distanceToDestiny <= destinyInRangeDistance || headTrf.position.y < destiny.transform.position.y) //Safety check. When jump is too fast distance can never be less than range distance { destinyInRange = true; JumpExitActions(); destiny.WormEnterExit(); } } if (headTrf.position.y < -WormBlackboard.NAVMESH_LAYER_HEIGHT) { SetHeadUnderground(); subState = SubState.EXITING; } break; case SubState.EXITING: currentX += Time.deltaTime * speed; lastPosition = headTrf.position; headTrf.position = bb.GetJumpPositionGivenX(currentX); headTrf.LookAt(headTrf.position + (headTrf.position - lastPosition)); if (bb.tailReachedMilestone) { Vector3 pos = headTrf.position; pos.y = -WormBlackboard.NAVMESH_LAYER_HEIGHT; headTrf.position = pos; //Trigger meteor rain MeteorAttackEventInfo info = MeteorAttackEventInfo.eventInfo; WormBlackboard.MeteorAttackSettings settings = bb.MeteorAttackSettingsPhase; info.meteorInitialBurst = settings.meteorInitialBurst; info.meteorRainDuration = settings.meteorRainDuration; info.meteorInterval = settings.meteorInterval; info.meteorsPerInterval = settings.meteorsPerInterval; info.meteorWaitTime = settings.meteorWaitTime; info.meteorWarningTime = settings.meteorWarningTime; rsc.eventMng.TriggerEvent(EventManager.EventType.METEOR_RAIN_START, info); subState = SubState.WAITING_METEOR_RAIN; } break; case SubState.WAITING_METEOR_RAIN: //Wait break; case SubState.METEOR_RAIN_ENDED: return(head.wanderingState); default: break; } return(null); }