public void Execute(IBattleParticipant target) { target.HpCurrent -= DamageAmount; if (Duration != 0) { Duration = (Duration == INFINITE) ? INFINITE : Duration - 1; } log.Debug($"Hit {target.Name} for {DamageAmount} damage ({target.HpCurrent}/{target.HpMax})"); }
private static IBattleParticipant FindSlowBoi(List <IBattleParticipant> bps) { IBattleParticipant slowboi = bps.First(); foreach (IBattleParticipant bp in bps) { if (slowboi.TurnMeterIncreaseOnClockTick > bp.TurnMeterIncreaseOnClockTick) { slowboi = bp; } } return(slowboi); }
public AutoBattle(IBattleParticipant attacker, IBattleParticipant defender, CommandContext c) { log = Serilog.Log.ForContext <AutoBattle>(); Attacker = attacker; Defender = defender; cmdCtx = c; Round = 0; CombatLog = new List <string>(); AttackerAttacks = new List <Attack>(); DefenderAttacks = new List <Attack>(); CombatId = Guid.NewGuid().ToString().Substring(0, 8); }
public void Setup(IBattleParticipant a, IBattleParticipant b) { transform.position = a.position; this.a = a; this.b = b; Vector3 dir = (b.position - a.position).normalized; float sign = dir.x < 0? -1f: 1f; transform.rotation = Quaternion.Euler(0, 0, sign * Mathf.Asin(dir.y) * Mathf.Rad2Deg); if (sign < 0) { Transform tmp = defenderMorale; defenderMorale = attackerMorale; attackerMorale = tmp; } UpdateMorale(true); StartCoroutine(Fight()); }
private IEnumerable <List <ClanBossBattleResult> > Run(bool exploreAllSequences, bool failOnKill) { Queue <CBBState> battleStates = new Queue <CBBState>(); battleStates.Enqueue(this.initialState); // While the queue isn't empty // run all possible next turns for the head of the queue state and enqueue those states // If someone is killed after the last unkillable turn, the run fails (no more enqueues) // If clan boss has turn 50, the run succeeds (return the result) while (battleStates.Count > 0) { CBBState state = battleStates.Dequeue(); bool returnResults = false; // Advance turn meter for each battle participant foreach (IBattleParticipant participant in state.BattleParticipants) { participant.ClockTick(); } // See who has the most turn meter double maxTurnMeter = double.MinValue; foreach (IBattleParticipant participant in state.BattleParticipants) { maxTurnMeter = Math.Max(maxTurnMeter, participant.TurnMeter); } // See if anybody has a full turn meter if (maxTurnMeter <= Constants.TurnMeter.Full) { // Nothing to do this time, re-enqueue this state. battleStates.Enqueue(state); } else { // Champion with the fullest turn meter takes a turn! IBattleParticipant maxTMChamp = state.BattleParticipants.First(bp => bp.TurnMeter == maxTurnMeter); foreach (Skill passive in maxTMChamp.GetPassiveSkills()) { if (passive.TurnAction.EffectsToApply != null) { foreach (EffectToApply effect in passive.TurnAction.EffectsToApply) { if (effect.WhenToApply == Constants.TimeInTurn.Beginning) { if (effect.Target == Constants.Target.Self) { maxTMChamp.ApplyEffect(effect.Effect); } else if (effect.Target == Constants.Target.AllAllies) { foreach (IBattleParticipant bp in state.BattleParticipants.Where(p => !p.IsClanBoss && p != maxTMChamp)) { bp.ApplyEffect(effect.Effect); } } } } } } IEnumerable <Skill> skillsToRun; Skill nextAISkill = maxTMChamp.NextAISkill(); if (exploreAllSequences && state.BattleParticipants.Where(bp => bp.IsClanBoss).First().TurnCount < AutoAfterClanBossTurn) { skillsToRun = maxTMChamp.AllAvailableSkills(); } else { skillsToRun = new List <Skill>() { maxTMChamp.NextAISkill() }; } CBBState currentState = state; foreach (Skill skill in skillsToRun) { state = new CBBState(currentState); IBattleParticipant champ = state.BattleParticipants.Where(bp => bp.Name == maxTMChamp.Name).First(); List <ClanBossBattleResult.Attack> additionalAttacks = new List <ClanBossBattleResult.Attack>(); champ.TakeTurn(skill); if (!champ.IsClanBoss) { TurnAction action = skill.TurnAction; additionalAttacks = ApplyTurnActions( skill, champ, state.BattleParticipants.Where(p => !p.IsClanBoss && p != champ), state.BattleParticipants.Where(p => !p.IsClanBoss), state.BattleParticipants.Where(p => p.IsClanBoss), state.BattleParticipants.Where(p => p.IsClanBoss).First() ); battleStates.Enqueue(state); } else { // Clan boss turn! TurnAction action = skill.TurnAction; bool enqueueNewState = true; List <IBattleParticipant> additionalAttackers = new List <IBattleParticipant>(); if (action.AttackTarget == Constants.Target.AllEnemies) { foreach (IBattleParticipant bp in state.BattleParticipants.Where(p => !p.IsClanBoss)) { bp.GetAttacked(action.AttackCount); if (bp.ActiveBuffs.ContainsKey(Constants.Buff.Counterattack) && !bp.ActiveDebuffs.ContainsKey(Constants.Debuff.Stun)) { additionalAttackers.Add(bp); } if (champ.TurnCount > LastKillableTurn && !bp.ActiveBuffs.ContainsKey(Constants.Buff.Unkillable)) { enqueueNewState = !failOnKill; } } } else if (action.AttackTarget == Constants.Target.OneEnemy) { IBattleParticipant stunTarget = this.GetStunTarget(state.BattleParticipants); stunTarget.GetAttacked(action.AttackCount); if (champ.TurnCount > LastKillableTurn && !stunTarget.ActiveBuffs.ContainsKey(Constants.Buff.Unkillable)) { enqueueNewState = !failOnKill; } if (action.DebuffsToApply != null) { stunTarget.ApplyDebuff(action.DebuffsToApply.First()); } if (stunTarget.ActiveBuffs.ContainsKey(Constants.Buff.Counterattack) && !stunTarget.ActiveDebuffs.ContainsKey(Constants.Debuff.Stun)) { additionalAttackers.Add(stunTarget); } } foreach (IBattleParticipant bp in additionalAttackers) { bp.AdditionalAttack(); additionalAttacks.Add(new ClanBossBattleResult.Attack(bp.Name, bp.TurnCount, bp.TurnMeter, Constants.SkillId.A1, bp.GetA1().Name, Constants.SkillId.A1)); } if (champ.TurnCount == MaxClanBossTurns) { // End of the run! enqueueNewState = false; returnResults = true; } if (enqueueNewState) { battleStates.Enqueue(state); } } List <ClanBossBattleResult.BattleParticipantStats> bpStats = new List <ClanBossBattleResult.BattleParticipantStats>(); foreach (IBattleParticipant bp in state.BattleParticipants) { ClanBossBattleResult.BattleParticipantStats bpStat = new ClanBossBattleResult.BattleParticipantStats(bp.Name, bp.IsClanBoss, bp.TurnMeter, new Dictionary <Constants.Buff, int>(bp.ActiveBuffs), new Dictionary <Constants.Debuff, int>(bp.ActiveDebuffs), bp.GetSkillToCooldownMap()); bpStats.Add(bpStat); } ClanBossBattleResult.Attack attackDetails = new ClanBossBattleResult.Attack(champ.Name, champ.TurnCount, maxTurnMeter, skill.Id, skill.Name, nextAISkill.Id); ClanBossBattleResult result = new ClanBossBattleResult(state.BattleParticipants.First(p => p.IsClanBoss).TurnCount, attackDetails, bpStats, additionalAttacks); state.Results.Add(result); if (returnResults) { yield return(state.Results); } } } } }
private static List <ClanBossBattleResult.Attack> ApplyTurnActions( Skill skill, IBattleParticipant active, IEnumerable <IBattleParticipant> allies, IEnumerable <IBattleParticipant> fullTeam, IEnumerable <IBattleParticipant> enemies, IBattleParticipant singleTargetEnemy) { List <ClanBossBattleResult.Attack> attacks = new List <ClanBossBattleResult.Attack>(); TurnAction action = skill.TurnAction; if (action.BuffsToApply != null) { foreach (BuffToApply buff in action.BuffsToApply) { if (buff.Target == Constants.Target.Self) { active.ApplyBuff(buff); } else if (buff.Target == Constants.Target.AllAllies) { foreach (IBattleParticipant bp in allies) { bp.ApplyBuff(buff); } } else if (buff.Target == Constants.Target.FullTeam) { foreach (IBattleParticipant bp in fullTeam) { bp.ApplyBuff(buff); } } } } if (action.DebuffsToApply != null) { foreach (DebuffToApply debuff in action.DebuffsToApply) { if (debuff.Target == Constants.Target.AllEnemies) { foreach (IBattleParticipant bp in enemies) { bp.ApplyDebuff(debuff); } } else if (debuff.Target == Constants.Target.OneEnemy) { singleTargetEnemy.ApplyDebuff(debuff); } } } if (action.EffectsToApply != null) { foreach (EffectToApply effect in action.EffectsToApply) { if (effect.Effect == Constants.Effect.AllyAttack) { foreach (IBattleParticipant bp in allies) { if (effect.Target == Constants.Target.ThreeRandomAllies && bp.LeaveOutOfAllyAttack) { continue; } bp.AdditionalAttack(); Skill a1 = bp.GetA1(); attacks.Add(new ClanBossBattleResult.Attack(bp.Name, bp.TurnCount, bp.TurnMeter, a1.Id, a1.Name, Constants.SkillId.A1)); attacks.AddRange(ApplyTurnActions( a1, bp, fullTeam.Where(p => p != bp), fullTeam, enemies, singleTargetEnemy)); } } else { if (effect.Target == Constants.Target.Self) { active.ApplyEffect(effect.Effect); } else if (effect.Target == Constants.Target.AllAllies) { foreach (IBattleParticipant bp in allies) { bp.ApplyEffect(effect.Effect); } } } } } foreach (Skill passive in active.GetPassiveSkills()) { if (passive.TurnAction.EffectsToApply != null) { foreach (EffectToApply effect in passive.TurnAction.EffectsToApply) { if (effect.WhenToApply == Constants.TimeInTurn.End) { if (effect.Target == Constants.Target.Self) { active.ApplyEffect(effect.Effect); } else if (effect.Target == Constants.Target.AllAllies) { foreach (IBattleParticipant bp in allies) { bp.ApplyEffect(effect.Effect); } } } } } } return(attacks); }