public override IEnumerator <AbilityDeliveryTarget> Deliver(AbilityExecutionContext context, TargetWrapper target) { UnitEntityData caster = context.MaybeCaster; if (caster == null) { UberDebug.LogError("Caster is missing", Array.Empty <object>()); yield break; } RulebookEventContext rulebookContext = context.RulebookContext; RuleAttackWithWeapon attackWithWeapon = (rulebookContext != null) ? rulebookContext.AllEvents.LastOfType <RuleAttackWithWeapon>() : null; RuleAttackWithWeapon ruleAttackWithWeapon = attackWithWeapon; RuleAttackRoll attackRoll = (ruleAttackWithWeapon != null) ? ruleAttackWithWeapon.AttackRoll : null; attackRoll = (attackRoll ?? context.TriggerRule <RuleAttackRoll>(new RuleAttackRoll(caster, target.Unit, caster.GetFirstWeapon(), 0))); if (attackWithWeapon == null) { attackRoll.ConsumeMirrorImageIfNecessary(); } yield return(new AbilityDeliveryTarget(target) { AttackRoll = attackRoll }); yield break; }
public override void RunAction() { //Main.DebugLog($"[ActionDealDamage2] Target:{Target?.Unit?.CharacterName} AC:{Target?.Unit?.Stats?.AC?.ModifiedValue} Flat-AC:{Target?.Unit?.Stats?.AC?.FlatFooted} Touch-AC:{Target?.Unit?.Stats?.AC?.Touch} Caster:{Context?.MaybeCaster?.CharacterName}"); //Main.DebugLog("Context[0] " + this.Context[AbilityRankType.Default].ToString()); //AbilityRankType.DamageDice [1] //AbilitySharedValue.Damage [0] //AbilitySharedValue.Duration [2] only composite //for (int i = 0; i < 7; i++) //{ // Main.DebugLog("AbilitySharedValue:" + Context[(AbilitySharedValue)i].ToString()); //} //for (int i = 0; i < 7; i++) //{ // Main.DebugLog("AbilityRankType:" + Context[(AbilityRankType)i].ToString()); //} if (this.Target.Unit == null) { UberDebug.LogError(this, "Invalid target for effect '{0}'", this.GetType().Name); } else if (this.Context.MaybeCaster == null) { UberDebug.LogError(this, "Invalid caster for effect '{0}'", this.GetType().Name); } else { bool saveSuccess = this.Context.SavingThrow != null && (this.Context.SavingThrow.IsPassed || this.Context.SavingThrow.ImprovedEvasion) && this.HalfIfSaved; if (saveSuccess && this.Context.SavingThrow.Evasion && this.Context.SavingThrow.IsPassed) { EventBus.RaiseEvent <IUnitEvasionHandler>(h => h.HandleEffectEvaded(this.Target.Unit, this.Context)); } else { RuleAttackRoll attackRoll; if (WeaponOverride != null) { attackRoll = new RuleAttackRoll(Context.MaybeCaster, this.Target.Unit, WeaponOverride, 0); if (this.Context[AbilitySharedValue.Heal] == 0) // if this is the first attack this context { this.Context.TriggerRule(attackRoll); this.Context[AbilitySharedValue.Heal] = attackRoll.Roll; // save this for other targets } else { //attackRoll.ImmuneToCriticalHit = true; // only the first target may get a crit attackRoll.SuspendCombatLog = true; // don't print, since the roll would be different this.Context.TriggerRule(attackRoll); } int d20 = this.Context[AbilitySharedValue.Heal]; // result of attack roll Main.DebugLog($"Attack:{d20} total:{d20 + attackRoll.AttackBonus} AC:{attackRoll.TargetAC} result:{attackRoll.Result.ToString()}"); if (attackRoll.Result == AttackResult.MirrorImage) { // battlelog notification that Mirror Image was hit? attackRoll.ConsumeMirrorImageIfNecessary(); return; } if (!this.IsSuccessRoll(d20, attackRoll.AttackBonus, attackRoll.TargetAC)) { return; } if (attackRoll.Result == AttackResult.Concealment) { // battlelog notification that concealment prevented hit Kingmaker.Game.Instance.UI.BattleLogManager.LogView.AddLogEntry(attackRoll.AttackLogEntry); return; } } else { attackRoll = ElementsContext.GetData <ContextAttackData>()?.AttackRoll; } ContextActionDealDamage2.DamageInfo info = new ContextActionDealDamage2.DamageInfo() { Dices = new DiceFormula(this.Value.DiceCountValue.Calculate(this.Context), this.Value.DiceType), Bonus = this.Value.BonusValue.Calculate(this.Context), PreRolledValue = !this.ReadPreRolledFromSharedValue ? new int?() : new int?(this.Context[this.PreRolledSharedValue]), HalfBecauseSavingThrow = saveSuccess, Empower = this.Context.HasMetamagic(Metamagic.Empower), Maximize = this.Context.HasMetamagic(Metamagic.Maximize), CriticalModifier = this.IgnoreCritical || attackRoll == null || !attackRoll.IsCriticalConfirmed ? new DamageCriticalModifierType?() : new DamageCriticalModifierType?(this.AbilityContext == null ? attackRoll.Weapon.Blueprint.CriticalModifier : DamageCriticalModifierType.X2) }; int num; switch (this.M_Type) { case ContextActionDealDamage2.Type.Damage: num = this.DealHitPointsDamage(info); break; case ContextActionDealDamage2.Type.AbilityDamage: num = this.DealAbilityScoreDamage(info); break; case ContextActionDealDamage2.Type.EnergyDrain: num = this.DrainEnergy(info); break; default: throw new ArgumentOutOfRangeException(); } if (this.WriteResultToSharedValue) { this.Context[this.ResultSharedValue] = num; } if (!this.WriteCriticalToSharedValue || attackRoll == null || !attackRoll.IsCriticalConfirmed) { return; } this.Context[this.CriticalSharedValue] = 1; } } }