public OffensiveSpell ApplySpell(LivingEntity caster, SpellSource spellSource) { var spell = spellSource.CreateSpell(caster); if (!gm.UtylizeSpellSource(caster, spellSource, spell)) { return(null); } if (spell is OffensiveSpell ps) { if (ps is SkeletonSpell skeletonSpell) { gm.AddAlly(skeletonSpell.Ally); } if (caster is Hero) { HandleHeroActionDone(); } return(ps); } else { gm.Logger.LogError("!OffensiveSpell " + spellSource); gm.ReportFailure(""); } return(null); }
public PassiveSpell ApplyPassiveSpell(LivingEntity caster, SpellSource spellSource, Point?destPoint = null) { var spell = spellSource.CreateSpell(caster); string preventReason = ""; if (!gm.Context.CanUseScroll(caster, spellSource, spell, ref preventReason)) { gm.ReportFailure(preventReason); return(null); } if (spell is PassiveSpell ps) { if (ps.Kind == SpellKind.Teleport) { if (destPoint != null) { var currentTile = gm.CurrentNode.GetTile(destPoint.Value); var teleportSpell = ps as TeleportSpell; if (teleportSpell.Range < gm.Hero.DistanceFrom(currentTile)) { gm.ReportFailure("Range of spell is too small (max:" + teleportSpell.Range + ")"); return(null); } if (currentTile.IsEmpty || currentTile is Loot) { gm.CurrentNode.SetTile(gm.Hero, destPoint.Value); } else { gm.ReportFailure("Can not cast on the pointed tile"); return(null); } } } else { caster.ApplyPassiveSpell(ps); } gm.UtylizeSpellSource(caster, spellSource, spell); gm.AppendAction <LivingEntityAction>((LivingEntityAction ac) => { ac.Kind = LivingEntityActionKind.Teleported; ac.Info = gm.Hero.Name + " used " + spellSource.Kind.ToDescription() + " scroll"; ac.InvolvedEntity = caster; }); if (caster is Hero) { HandleHeroActionDone(); } return(ps); } else { gm.Logger.LogError("!PassiveSpell " + spellSource); gm.ReportFailure(""); } return(null); }
public PassiveSpell ApplyPassiveSpell(LivingEntity caster, SpellSource spellSource, Point?destPoint = null) { var spell = spellSource.CreateSpell(caster); string preventReason = ""; if (!gm.Context.CanUseScroll(caster, spellSource, spell, ref preventReason)) { gm.ReportFailure(preventReason); return(null); } if (spell is PassiveSpell ps) { if (ps.Kind == SpellKind.Teleport) { if (destPoint != null) { var currentTile = gm.CurrentNode.GetTile(destPoint.Value); var teleportSpell = ps as TeleportSpell; if (teleportSpell.Range < gm.Hero.DistanceFrom(currentTile)) { gm.ReportFailure("Range of spell is too small (max:" + teleportSpell.Range + ")"); return(null); } if (currentTile.IsEmpty || currentTile is Loot) { gm.CurrentNode.SetTile(gm.Hero, destPoint.Value); } else { gm.ReportFailure("Can not cast on the pointed tile"); return(null); } } } else if (ps.Kind == SpellKind.Dziewanna) { int maxApples = 1; if (RandHelper.GetRandomDouble() > 0.5) { maxApples += 1; } for (int appleIndex = 0; appleIndex < maxApples; appleIndex++) { var enemies = gm.CurrentNode.GetNeighborTiles <Enemy>(gm.Hero); bool added = false; foreach (var en in enemies) { var emptyOnes = gm.CurrentNode.GetEmptyNeighborhoodTiles(en, false); if (emptyOnes.Any()) { AddApple(emptyOnes.First()); added = true; break; } } if (!added) { var emp = gm.CurrentNode.GetClosestEmpty(gm.Hero); AddApple(emp); } } } else { caster.ApplyPassiveSpell(ps); } gm.UtylizeSpellSource(caster, spellSource, spell); gm.AppendAction <LivingEntityAction>((LivingEntityAction ac) => { ac.Kind = LivingEntityActionKind.Teleported; ac.Info = gm.Hero.Name + " used " + spellSource.Kind.ToDescription() + " scroll"; ac.InvolvedEntity = caster; }); if (caster is Hero) { HandleHeroActionDone(); } return(ps); } else { gm.Logger.LogError("!PassiveSpell " + spellSource); gm.ReportFailure(""); } return(null); }
public bool ApplyAttackPolicy ( LivingEntity caster,//hero, enemy, ally Tiles.Abstract.IObstacle target, SpellSource spellSource, Action <Policy> BeforeApply = null, Action <Policy> AfterApply = null, bool looped = false ) { if (!looped) { applyingBulk = false; } var spell = spellSource.CreateSpell(caster) as IProjectileSpell; if (spell != null) { if (!caster.IsInProjectileReach(spell, target.Position)) { this.gm.SoundManager.PlayBeepSound(); this.gm.AppendAction(new GameEvent() { Info = "Target out of range" }); return(false); } } if (!looped && !gm.UtylizeSpellSource(caster, spellSource, spell)) { return(false); } var policy = Container.GetInstance <ProjectileCastPolicy>(); policy.Target = target as Dungeons.Tiles.Tile; policy.ProjectilesFactory = Container.GetInstance <IProjectilesFactory>(); policy.Projectile = spellSource.CreateSpell(caster) as IProjectileSpell; if (BeforeApply != null) { BeforeApply(policy); } policy.OnApplied += (s, e) => { var le = policy.TargetDestroyable is LivingEntity; if (!le)//le is handled specially { this.gm.LootManager.TryAddForLootSource(policy.Target as ILootSource); //dest.Destroyed = true; } if (looped) { return; } if (!applyingBulk) { var repeatOK = caster.IsStatRandomlyTrue(EntityStatKind.ChanceToRepeatElementalProjectileAttack); if (repeatOK) { ApplyAttackPolicy(caster, target, spellSource, BeforeApply, AfterApply, true); } } if (caster is Hero) { OnHeroPolicyApplied(policy); } if (AfterApply != null) { AfterApply(policy); } }; policy.Apply(caster); var bulkOK = false; if (target is Enemy en && spellSource is WeaponSpellSource) { bulkOK = HandleBulk(en, EntityStatKind.ChanceToElementalProjectileBulkAttack, (Enemy en1) => { applyingBulk = true; ApplyAttackPolicy(caster, en1, spellSource, BeforeApply, AfterApply, true); }); } return(true); }
public ApplyAttackPolicyResult ApplyAttackPolicy ( LivingEntity caster,//hero, enemy, ally Tiles.Abstract.IObstacle target, SpellSource spellSource, Action <Policy> BeforeApply = null, Action <Policy> AfterApply = null, bool looped = false ) { if (!looped) { applyingBulk = false; } var spell = spellSource.CreateSpell(caster) as IProjectileSpell; if (spell != null) { if (!caster.IsInProjectileReach(spell, target.Position)) { this.gm.SoundManager.PlayBeepSound(); this.gm.AppendAction(new GameEvent() { Info = "Target out of range" }); return(ApplyAttackPolicyResult.OutOfRange); } } if (!looped && !gm.UtylizeSpellSource(caster, spellSource, spell)) { return(ApplyAttackPolicyResult.NotEnoughResources); } var policy = Container.GetInstance <ProjectileCastPolicy>(); policy.AddTarget(target); policy.ProjectilesFactory = Container.GetInstance <IProjectilesFactory>(); policy.Projectile = spellSource.CreateSpell(caster) as IProjectileSpell; if (BeforeApply != null) { BeforeApply(policy); } policy.OnApplied += (s, e) => { gm.CallTryAddForLootSource(policy.Targets.First()); if (looped) { return; } if (!applyingBulk) { var repeatOK = caster.IsStatRandomlyTrue(EntityStatKind.ChanceToRepeatElementalProjectileAttack); if (repeatOK) { ApplyAttackPolicy(caster, target, spellSource, BeforeApply, AfterApply, true); } } gm.FinishPolicyApplied(caster, AfterApply, policy); }; policy.Apply(caster); var bulkOK = false; if (target is Enemy en && spellSource is WeaponSpellSource) { bulkOK = HandleBulk(en, EntityStatKind.ChanceToElementalProjectileBulkAttack, (Enemy en1) => { applyingBulk = true; ApplyAttackPolicy(caster, en1, spellSource, BeforeApply, AfterApply, true); gm.AppendAction(caster.Name + " used Projectile Bulk Attack", ActionLevel.Important); }); } return(ApplyAttackPolicyResult.OK); }