private IEnumerator FlowerFiring() { isRaged = true; battleState = BossBattleState.FLOWER; GetComponent <SpriteRenderer>().color = new Color(1, 0.2f, 0); transform.DOScaleX(20, 0.5f); transform.DOScaleY(20, 0.5f); transform.DOMoveX(152, 1); yield return(new WaitForSeconds(2)); StartCoroutine(FlowerShot(60, 19)); }
private IEnumerator FlowerShot(int count, float offset) { for (int i = 0; i < count; i++) { yield return(new WaitForSeconds(0.13f)); FireBullet(bullet, Quaternion.AngleAxis(offset * i, Vector3.forward) * Vector3.up); FireBullet(bullet, Quaternion.AngleAxis(offset * i + 60, Vector3.forward) * Vector3.up); FireBullet(bullet, Quaternion.AngleAxis(offset * i + 120, Vector3.forward) * Vector3.up); FireBullet(bullet, Quaternion.AngleAxis(offset * i + 180, Vector3.forward) * Vector3.up); FireBullet(bullet, Quaternion.AngleAxis(offset * i + 240, Vector3.forward) * Vector3.up); FireBullet(bullet, Quaternion.AngleAxis(offset * i + 300, Vector3.forward) * Vector3.up); } battleState = BossBattleState.RAGED; }
public void ExecuteSkill(BattleActor target, bool forceAction = false) { if (executeActionRoutine == null) { if (currentActor.QueuedSkill != null && !forceAction) { // We have a skill that needs to be delayed currentActor.QueuedSkillTarget = target; currentActor.TriggerCast(); // Clean up the turn // Set the turn order currentActor.CurrentSpeedOffset += currentActor.AverageSpeed * currentActor.QueuedSkill.CastDelay; currentActor.TemporaryOffset = 0f; foreach (BattleActor actor in TurnOrder) { if (actor is BossActor) { actor.TemporaryOffset = 0f; } } SortTurnOrder(); // Hide the Menu battleInterface.HideMemberArea(); // Do the action executeActionRoutine = null; bossActionRoutine = null; state = BossBattleState.ExecuteAction; } else { currentActor.StopCast(); executeActionRoutine = ExecuteSkillTiming(target); StartCoroutine(executeActionRoutine); } } }
private void UpdateState() { if (battleState != BossBattleState.FLOWER && battleState != BossBattleState.RAMPANT) { if (isEngaged) { battleState = BossBattleState.NORMAL; } if (isRaged) { battleState = BossBattleState.RAGED; } if (health < 0) { battleState = BossBattleState.DEAD; } } }
private IEnumerator Rampant() { battleState = BossBattleState.RAMPANT; transform.DOMoveX(171, 1).OnComplete(() => { DOTween.Sequence() .Append(transform.DOMoveX(133, 1f).SetEase(Ease.Linear)) .Append(transform.DOShakeScale(0.5f, 10, 100)) .Join(walls[0].DOShakePosition(0.5f, 0.2f, 3)) .Join(walls[1].DOShakePosition(0.5f, 0.2f, 3)) .Join(walls[2].DOShakePosition(0.5f, 0.2f, 3)) .Join(walls[3].DOShakePosition(0.5f, 0.2f, 3)) .Append(transform.DOMoveX(171, 1f).SetEase(Ease.Linear)) .Append(transform.DOShakeScale(0.5f, 10, 100)) .Join(walls[0].DOShakePosition(0.5f, 0.2f, 3)) .Join(walls[1].DOShakePosition(0.5f, 0.2f, 3)) .Join(walls[2].DOShakePosition(0.5f, 0.2f, 3)) .Join(walls[3].DOShakePosition(0.5f, 0.2f, 3)) .SetLoops(3).OnComplete(() => battleState = BossBattleState.RAGED); }); yield return(null); }
public IEnumerator EndOfTurnCleanUp() { // Put UI/Death stuff here if we have something special at the end of the turn // Execute Dieing Actors OnDeath Skills foreach (BattleActor actor in OnDeathSkillExecutionList.Keys) { currentActor = actor; // may not want to set the current actor, need to test to verify currentSkill = OnDeathSkillExecutionList[actor]; // Get the required target BattleActor target = GetTargetBasedOnSkill(currentSkill, currentActor); print("Executing " + currentSkill.name + " [" + target + "]"); if (!OnDeathSkillExecutionList[actor].OneTimeTrigger) { yield return(StartCoroutine(ExecuteSkillTiming(target))); } else { Debug.Log("Triggered Once: " + OnDeathSkillExecutionList[actor].triggeredOnce); if (!OnDeathSkillExecutionList[actor].triggeredOnce) { yield return(StartCoroutine(ExecuteSkillTiming(target))); OnDeathSkillExecutionList[actor].triggeredOnce = true; } } } OnDeathSkillExecutionList.Clear(); // Next Turn yield return(new WaitForSeconds(1f)); state = BossBattleState.NewTurn; }
IEnumerator ExecuteSkillTiming(BattleActor target, BattleActor alternativeActor = null) { // Check skill type, if its an AOE skill send in all of the targets, if its a singletarget skill send in the selected target List <BattleActor> targets = new List <BattleActor>(); //if (alternativeActor == null) // we may need this but need to be careful with the turn delay section when enabling it alternativeActor = currentActor; print("Skill Timing: " + alternativeActor); currentSkill.Init(alternativeActor); if (currentSkill.TargetType == SkillTargetType.SingleTarget) { // TODO Verify the selected Target switch (currentSkill.skillTargeting) { case SkillTargeting.Self: targets.Add(alternativeActor); break; case SkillTargeting.Enemy: case SkillTargeting.Party: targets.Add(target); break; } } else { // Get all the targets based on the skill type switch (currentSkill.skillTargeting) { case SkillTargeting.Enemy: // Get all of the BossActor Targets if (alternativeActor is HeroActor) { foreach (BattleActor actor in TurnOrder) { if (actor is BossActor) { targets.Add(actor); } } } else if (alternativeActor is BossActor) { foreach (HeroActor hero in Party) { targets.Add(hero); } } break; case SkillTargeting.Party: case SkillTargeting.AllParty: // Get all the heroActors if (alternativeActor is HeroActor) { foreach (HeroActor hero in Party) { targets.Add(hero); } } else if (alternativeActor is BossActor) { foreach (BattleActor actor in TurnOrder) { if (actor is BossActor) { targets.Add(actor); } } } break; } } print("Skill Timing targets count: " + targets.Count); if (targets.Count < 1) { targets.Add(target); } yield return(StartCoroutine(currentSkill.ExecuteSkill(targets))); // Set the turn order if (alternativeActor is HeroActor && ((HeroActor)alternativeActor).TurnDelay != null && Random.Range(0f, 1f) < ((HeroActor)alternativeActor).TurnDelay.chance) { alternativeActor.CurrentSpeedOffset += alternativeActor.AverageSpeed * ((HeroActor)alternativeActor).TurnDelay.delayWeight; } else { alternativeActor.CurrentSpeedOffset += alternativeActor.AverageSpeed * currentSkill.Weight; } alternativeActor.TemporaryOffset = 0f; SortTurnOrder(); // Hide the Menu battleInterface.HideMemberArea(); // Do the action executeActionRoutine = null; bossActionRoutine = null; state = BossBattleState.ExecuteAction; }
void RunBattleSimulation() { // 2 states - Select Action and Execute Action // on select action set the actor to the current // show the UI for where the default action will place them switch (state) { case BossBattleState.EndOfTurn: break; case BossBattleState.NewTurn: // Clean up the list of dead actors List <BattleActor> removeList = new List <BattleActor>(); foreach (BattleActor actor in TurnOrder) { if (actor.Health <= 0f) { actor.StopCast(); battleInterface.RemoveActorPortrait(actor); removeList.Add(actor); deadActors.Add(actor); if (actor is BossActor) { ((BossActor)actor).handler.Die(); } else { ((HeroActor)actor).handler.Die(); } } } bool bossKilled = false; foreach (BattleActor actor in removeList) { if (actor is BossActor) { bossKilled = true; } TurnOrder.Remove(actor); } if (bossKilled) { // on allyDeathTrigger foreach (BattleActor actor in TurnOrder) { if (actor is BossActor) { ((BossActor)actor).OnAllyDeath(); } } } currentActor = TurnOrder[0]; selector.GoToTarget(currentActor.GetGameObject().transform.position); if (currentActor is HeroActor) { print(" --- [New Turn]\n Hero Turn: " + currentActor.Name); } else { print(" --- [New Turn]\n Boss Turn: " + currentActor.Name); } // Check if the current actor is stunned here and skip their turn if (currentActor.IsStunned()) { // Spawn text displaying this actor is stunned then return to restart this turn and choose a new actor currentActor.UpdateStatusEffects(StatusTriggerTime.StartOfTurn); currentActor.UpdateStatusEffects(StatusTriggerTime.EndOfTurn); return; } // this position allows stun transitions to be delayed when stunned, we can move this above the stun code block to change this if (currentActor is BossActor) { ((BossActor)currentActor).UpdateTurnCount(); } //Check for end of battle here if (IsBattleComplete()) { state = BossBattleState.EndOfBattle; } else { // Check if the actor has a skill waiting to be used if (currentActor.HasQueuedSkill()) { // Skip straight to the use the skill part of a turn SelectSkill(currentActor.QueuedSkill); ExecuteSkill(currentActor.QueuedSkillTarget, true); currentActor.QueuedSkill = null; currentActor.QueuedSkillTarget = null; } else { state = BossBattleState.SelectAction; } } break; case BossBattleState.SelectAction: battleInterface.SetCurrentTurn(currentActor); currentActor.UpdateStatusEffects(StatusTriggerTime.StartOfTurn); // Load UI for the hero or hide it on enemy if (currentActor is HeroActor) { // Reduce skill cooldowns by a turn foreach (Skill skill in ((HeroActor)currentActor).hero.Skills) { /*if (((HeroActor) currentActor).hero.Skills[skill] > 0) * ((HeroActor) currentActor).hero.Skills[skill] -= 1;*/ if (skill._cooldown > 0) { skill._cooldown--; } } battleInterface.ShowMemberArea((HeroActor)currentActor); SelectSkill(((HeroActor)currentActor).hero.Skills[((HeroActor)currentActor).hero.Skills.Count - 1]); // default skill selected bossTurn = false; } else { SelectSkill(((BossActor)currentActor).boss.Skills[0]); // Choose a skill based on how many targets int targetCount = 0; bool targetCasting = false; foreach (HeroActor actor in Party) { if (actor.Health > 0) { targetCount++; } if (actor.QueuedSkill != null) { targetCasting = true; } } Skill skillSelect = null; foreach (Skill skill in ((BossActor)currentActor).boss.Skills) { if (skill._cooldown < 1 && skill.CanInterrupt) { skillSelect = skill; } } // TODO put the interrupt AI chance on the boss data it self, current set to 25% of the time if (targetCasting && Random.Range(0f, 1f) < 0.25f && skillSelect != null) { // Choose the skill that can interrupt SelectSkill(skillSelect); } else if (targetCount > 2) { // It can be an AOE skill bool hasAOE = false; foreach (Skill skill in ((BossActor)currentActor).boss.Skills) { if (skill._cooldown < 1 && skill.TargetType != SkillTargetType.SingleTarget) { hasAOE = true; SelectSkill(skill); continue; } } if (!hasAOE) { foreach (Skill skill in ((BossActor)currentActor).boss.Skills) { if (skill._cooldown < 1) { SelectSkill(skill); continue; } } } } else { // Not AOE skill foreach (Skill skill in ((BossActor)currentActor).boss.Skills) { if (skill._cooldown < 1) { SelectSkill(skill); continue; } } } // if target count is >= 3 then you can use an AOE skill // otherwise use your best ability thats not an attack // if no other abilities then use an attack bossTurn = true; } state = BossBattleState.WaitForAction; break; case BossBattleState.ExecuteAction: //print("Execute Action"); // Do Queued Actions then (if there is a heal on multiple members or an attack that hits multiple targets etc) if (!PlayerPrefs.HasKey("tutorial_boss_battle_castable_skill")) { foreach (BattleActor actor in TurnOrder) { if (actor is BossActor && ((BossActor)actor).QueuedSkill != null) { StoryManager.Instance.DisplayStory("story_tutorial_boss_battle_interrupt"); PlayerPrefs.SetInt("tutorial_boss_battle_castable_skill", 1); } } } // go to the next actor currentActor.UpdateStatusEffects(StatusTriggerTime.EndOfTurn); //state = BossBattleState.NewTurn; StartEndOfTurn(); break; case BossBattleState.WaitForAction: // Update the turn order position based on selected skill if (bossTurn && bossActionRoutine == null) { AIActionSelect(); } // Select skill from UI // on target select add the ability to the queue and if (Input.GetMouseButtonDown(0) && !bossTurn && executeActionRoutine == null) { // see what we tapped, but for now just use the action RaycastHit2D hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition), Vector2.zero); //fctLocation = Camera.main.ScreenToWorldPoint(Input.mousePosition); if (hit.collider != null) { BattleActor target = null; //Debug.Log("Target Position: " + hit.collider.gameObject.transform.position + " | hit: " + hit.collider.gameObject.name); CharacterHandler h_handler = hit.collider.gameObject.GetComponent <CharacterHandler>(); if (h_handler != null) { print("Have CharacterHandler"); // Is a hero foreach (BattleActor hA in TurnOrder) { if (hA is HeroActor) { if (((HeroActor)hA).handler == h_handler) { target = hA; } } } print(target); if (target != null) { ExecuteSkill(target); } } MonsterHandler m_handler = hit.collider.gameObject.GetComponent <MonsterHandler>(); if (m_handler != null) { // Is a monster foreach (BattleActor bA in TurnOrder) { if (bA is BossActor) { if (((BossActor)bA).handler == m_handler) { target = bA; } } } //print(target); if (target != null) { ExecuteSkill(target); } } } } break; case BossBattleState.EndOfBattle: bool heroStillExists = false; bool bossStillExists = false; foreach (BattleActor actor in TurnOrder) { if (actor is HeroActor) { heroStillExists = true; } if (actor is BossActor) { bossStillExists = true; } } ActiveExploration activeZone = playerMan.SelectedBattle; if (!bossStillExists) { // Player won float chance = 0.2f + Mathf.Min((activeZone.TreasureFind / 3000f), 0.75f) * 0.8f; for (int i = 0; i < dataMan.globalData.GetGlobalAsInt(GlobalProps.ZONE_MONSTER_COUNT); i++) { if (Random.Range(0f, 1f) <= chance) { LootCrateScreenInterface.GenerateLootCrate(activeZone, MagicFindBoostMultiplier: playerMan.GetBoost(BoostType.MagicFind)); } } for (int i = 0; i < activeZone.ChestsEarned; i++) { LootCrateScreenInterface.GenerateLootCrate(activeZone, MagicFindBoostMultiplier: playerMan.GetBoost(BoostType.MagicFind)); } LootCrateScreenInterface.GenerateLootCrate(activeZone, TriggerInterfaceAfterLootCratesAdded, true, playerMan.GetBoost(BoostType.MagicFind)); } else if (!heroStillExists) { // Player was defeated StartCoroutine(ResurrectForGems(activeZone)); } playerMan.CurrentLeaderSkill = null; state = BossBattleState.ShowResults; break; case BossBattleState.ShowResults: break; } }
void StartEndOfTurn() { state = BossBattleState.EndOfTurn; StartCoroutine(EndOfTurnCleanUp()); }