/// <summary> /// Find all cells where a spell can be cast, from casterCell position /// Todo : takes traps into account /// </summary> /// <param name="caster"></param> /// <param name="casterCell"></param> /// <param name="actors"></param> /// <returns></returns> private IEnumerable <Cell> GetCellsAtSpellRange(PlayedFighter caster, Cell casterCell, IEnumerable <Fighter> actors) { int maxRange = caster.GetRealSpellRange(LevelTemplate); if (LevelTemplate.castTestLos) { _losMap.UpdateTargetCell(casterCell, true, false); } Func <Cell, bool> filter = cell => { if (LevelTemplate.castInLine || LevelTemplate.castInDiagonal) { if (!(LevelTemplate.castInLine && (casterCell.X == cell.X || casterCell.Y == cell.Y) || LevelTemplate.castInDiagonal && (Math.Abs(casterCell.X - cell.X) == Math.Abs(casterCell.Y - cell.Y)))) { return(false); } } if (LevelTemplate.castTestLos) { if (!_losMap[cell]) { return(false); } } if (LevelTemplate.needFreeCell) { if (!(cell.Walkable && !cell.NonWalkableDuringFight && cell != casterCell && !actors.Any(actor => actor.Cell != null && actor.Cell.Id == cell.Id))) { return(false); } } if (LevelTemplate.needTakenCell) { if (!(cell == casterCell || actors.Any(actor => actor.Cell != null && actor.Cell.Id == cell.Id))) { return(false); } } if (LevelTemplate.needFreeTrapCell) { return(false); // Do not play traps yet } int?targetId = caster.Fight.GetActorsOnCell(cell).Select(actor => (int?)actor.Id).FirstOrDefault(); if (targetId != null) { if (!IsAvailable(targetId)) { return(false); } } return(true); }; return(casterCell.GetAllCellsInRange((int)LevelTemplate.minRange, maxRange, false, filter)); }
private void StartAI() { var nearestMonster = GetNearestEnemy(); var shortcut = m_character.Character.SpellShortcuts.Shortcuts.FirstOrDefault(sc => sc.Slot == 1); if (shortcut == null) { m_character.Character.SendMessage("No spell on slot 1"); return; } var spell = shortcut.GetSpell(); if (spell == null) { m_character.Character.SendMessage("No spell on slot 1"); return; } if (m_character.IsInSpellRange(nearestMonster.Cell, spell.LevelTemplate)) { m_character.CastSpell(spell, nearestMonster.Cell); MoveFar(); m_character.PassTurn(); } else { MoveNear(nearestMonster, (int)(m_character.Cell.ManhattanDistanceTo(nearestMonster.Cell) - m_character.GetRealSpellRange(spell.LevelTemplate))); // wait until the movement ends if (m_stopMovingDelegate != null) { Bot.Character.Fighter.StopMoving -= m_stopMovingDelegate; m_stopMovingDelegate = null; } m_stopMovingDelegate = (sender, behavior, canceled, refused) => OnStopMoving(spell, nearestMonster, canceled, refused); Bot.Character.Fighter.StopMoving += m_stopMovingDelegate; } }