/// <summary> /// Inflict damage onto this character. /// The actual amount still needs to be determined by the current /// state of the game. eg: The presence of immunity effects can cause /// the damage to be ignored. /// </summary> /// <param name="source"></param> /// <param name="damage"></param> /// <returns></returns> public int TakeDamage(IPlayable source, int damage) { var hero = this as Hero; var minion = this as Minion; if (minion != null && minion.Zone.Type != Enums.Zone.PLAY) { return(0); } bool fatigue = hero != null && this == source; if (fatigue) { hero.Fatigue = damage; } if (minion != null && minion.HasDivineShield) { Game.Log(LogLevel.INFO, BlockType.ACTION, "Character", !Game.Logging? "":$"{this} divine shield absorbed incoming damage."); minion.HasDivineShield = false; return(0); } int armor = hero?.Armor ?? 0; int amount = hero == null ? damage : armor < damage ? damage - armor : 0; // added pre damage PreDamage = amount; // Predamage triggers (Ice Block) if (PreDamageTrigger != null) { PreDamageTrigger.Invoke(this); amount = PreDamage; } if (IsImmune) { Game.Log(LogLevel.INFO, BlockType.ACTION, "Character", !Game.Logging ? "" : $"{this} is immune."); PreDamage = 0; return(0); } // remove armor first from hero .... if (armor > 0) { hero.Armor = armor < damage ? 0 : armor - damage; } // final damage is beeing accumulated Damage += amount; Game.Log(LogLevel.INFO, BlockType.ACTION, "Character", !Game.Logging? "":$"{this} took damage for {PreDamage}({damage}). {(fatigue ? "(fatigue)" : "")}"); // reset predamage PreDamage = 0; //LastAffectedBy = source.Id; TODO // Damage event is created // Collect all the tasks and sort them by order of play // Death phase and aura update are not emerge here // place event related data Game.TaskQueue.StartEvent(); EventMetaData temp = Game.CurrentEventData; Game.CurrentEventData = new EventMetaData(source, this, amount); // on-damage triggers TakeDamageTrigger?.Invoke(this); Game.TriggerManager.OnDamageTrigger(this); Game.TriggerManager.OnDealDamageTrigger(source); Game.ProcessTasks(); Game.TaskQueue.EndEvent(); Game.CurrentEventData = temp; if (source.HasLifeSteal && !_lifestealChecker) { if (_history) { Game.PowerHistory.Add(PowerHistoryBuilder.BlockStart(BlockType.TRIGGER, source.Id, source.Card.Id, -1, 0)); // TriggerKeyword=LIFESTEAL } Game.Log(LogLevel.VERBOSE, BlockType.ATTACK, "TakeDamage", !_logging ? "" : $"lifesteal source {source} has damaged target for {amount}."); source.Controller.Hero.TakeHeal(source, amount); if (_history) { Game.PowerHistory.Add(new PowerHistoryBlockEnd()); } if (source.Controller.Hero.ToBeDestroyed && source.Controller.Hero.Health > 0) { source.Controller.Hero.ToBeDestroyed = false; } } if (this is Hero h) { h.IsDamagedThisTurn = true; } return(amount); }
/// <summary> /// Inflict damage onto this character. /// The actual amount still needs to be determined by the current /// state of the game. eg: The presence of immunity effects can cause /// the damage to be ignored. /// </summary> /// <param name="source"></param> /// <param name="damage"></param> /// <returns></returns> public int TakeDamage(IPlayable source, int damage) { var hero = this as Hero; var minion = this as Minion; bool fatigue = hero != null && this == source; if (fatigue) { hero.Fatigue = damage; } if (minion != null && minion.HasDivineShield) { Game.Log(LogLevel.INFO, BlockType.ACTION, "Character", !Game.Logging? "":$"{this} divine shield absorbed incoming damage."); minion.HasDivineShield = false; return(0); } int armor = hero?.Armor ?? 0; // added pre damage int preDamage = hero == null ? damage : armor < damage ? damage - armor : 0; PreDamage = preDamage; // Predamage triggers Game.TaskStack.SetDamageMetaData(source, this); PreDamageTrigger?.Invoke(this, preDamage); // reflect changes from tasks preDamage = PreDamage; if (this.IsImmune) { Game.Log(LogLevel.INFO, BlockType.ACTION, "Character", !Game.Logging? "":$"{this} is immune."); PreDamage = 0; Trigger.Invalidate(Game, SequenceType.DamageDealt); return(0); } // remove armor first from hero .... if (armor > 0) { hero.Armor = armor < damage ? 0 : armor - damage; } // final damage is beeing accumulated Damage += preDamage; Game.Log(LogLevel.INFO, BlockType.ACTION, "Character", !Game.Logging? "":$"{this} took damage for {PreDamage}({damage}). {(fatigue ? "(fatigue)" : "")}"); // check if there was damage done int tookDamage = preDamage; // reset predamage PreDamage = 0; LastAffectedBy = source.Id; // Damage event is created // Collect all the tasks and sort them by order of play // Death phase and aura update is not emerge here // on-damage triggers Game.TaskQueue.StartEvent(); Game.TriggerManager.OnDamageTrigger(this); Game.TriggerManager.OnDealDamageTrigger(source, preDamage); Game.ProcessTasks(); Game.TaskQueue.EndEvent(); if (source.HasLifeSteal && !_lifestealChecker) { if (_history) { Game.PowerHistory.Add(PowerHistoryBuilder.BlockStart(BlockType.TRIGGER, source.Id, source.Card.Id, -1, 0)); // TriggerKeyword=LIFESTEAL } Game.Log(LogLevel.VERBOSE, BlockType.ATTACK, "TakeDamage", !_logging ? "" : $"lifesteal source {source} has damaged target for {preDamage}."); source.Controller.Hero.TakeHeal(source, preDamage); if (_history) { Game.PowerHistory.Add(new PowerHistoryBlockEnd()); } if (source.Controller.Hero.ToBeDestroyed && source.Controller.Hero.Health > 0) { source.Controller.Hero.ToBeDestroyed = false; } } return(tookDamage); }