public static bool AbilityCanTarget(QueuedAbility queuedAbility) { //ability can target if the target is alive, or the target is dead but we have appropriate retarget behavior if (queuedAbility.Target.IsAlive == false && queuedAbility.Ability.DeadTargetBehavior == DeadTargetBehavior.AbandonAbilityExecution) { return false; } return true; }
protected void HandleQueuedAbilityActivation(QueuedAbility queuedAbility) { //TODO: When a battle entity dies, reset their HasQueuedAbility flag. //if the source has died since this ability was queued, just bail. We can't do anything else if (queuedAbility.Source.IsAlive == false) { return; } //we will be trying to execute the ability //start by setting the executing ability. This will display the name of the ability, as well as signal that we're busy processing this ability BattleModel.Instance.BattlefieldData.ExecutingAbility = queuedAbility.Ability; //first, we need to queue up the battle entity attack animation, followed by the logic to execute the ability steps var abilityExecutionSteps = new List<DelayedAction> { //start with battle entity attack animation DelayedAction.New(() => { if (queuedAbility.Source is PartyMemberInBattle) { //TODO: Party member step forward? } else { (queuedAbility.Source as EnemyInBattle).SpriteSheet.AttackFlash(); } }, 0) //no delay here, the step animations will handle their individual delay }; //next, we check to see if our target is still valid. If it's not, we'll skip the actual execution of the ability if (BattleUtility.AbilityCanTarget(queuedAbility)) { //we have a source that's alive, and can actually get targets. We need to check the costs of the ability //like does the source have enough energy, or does the item exist in inventory if (queuedAbility.Ability.ExecuteCost(queuedAbility.Source.BattleEntity)) { //we met all of our ability costs, we can execute the steps foreach (var step in queuedAbility.Ability.GetAbilitySteps(queuedAbility.Source.BattleEntity)) { var allTargets = new BattleEntityInBattle[0]; abilityExecutionSteps.Add(DelayedAction.New(() => { //retarget the primary target, if necessary queuedAbility.Target = BattleUtility.GetPrimaryTargetForAbilityStep(queuedAbility.Source, queuedAbility.Target, queuedAbility.Ability.DeadTargetBehavior); //get secondary targets based on new primary target allTargets = BattleUtility.GetAllTargetsForAbilityStep(queuedAbility.Source, queuedAbility.Target, queuedAbility.Ability.Target, step); }, 1)); //handle ability animations (in parallel) abilityExecutionSteps.Add(DelayedAction.New( () => BattleUtility.HandleAbilityStepAnimations(queuedAbility.Source, allTargets, step.Animation), step.GetTotalFrames(GameState.InBattle))); //apply effects to targets, long enough to display damage/battle status abilityExecutionSteps.Add(DelayedAction.New( () => step.ApplyEffectToTargets(queuedAbility.Source.BattleEntity, allTargets.Select(x => x.BattleEntity).ToArray()), Constants.BATTLE_TIMING_DISPLAY_DAMAGE_TICKS)); } } else { //TODO: Do we want to somehow signal that we couldn't execute a prerequesite? (no energy, or no item in inventory, etc...) //TODO: BATTLE_TIMING_ABILITY_FAILED_COST_WAIT_TICKS may be reudced (or completely eliminted) when I get the step forward / step back animations taken care of. abilityExecutionSteps.Add(DelayedAction.New(() => { }, Constants.BATTLE_TIMING_ABILITY_FAILED_COST_WAIT_TICKS)); //just delay for a few seconds } } //TODO: We need to handle the situation of the party member stepping back as well //finally, queue up finish queued ability logic abilityExecutionSteps.Add(DelayedAction.New( () => Bus.Broadcast(BattleQueuedAbilityFinishedMessage.New(queuedAbility)), 0)); //TODO: Also, do we want actions for things such as checking to see if the battle is won/lost, if things have died, etc... TimerUtility.ExecuteChainOfActions(abilityExecutionSteps); }
protected BattleQueuedAbilityFinishedMessage(QueuedAbility queuedAbility) { QueuedAbility = queuedAbility; }
public static BattleQueuedAbilityFinishedMessage New(QueuedAbility queuedAbility) { return new BattleQueuedAbilityFinishedMessage(queuedAbility); }