/// <summary> /// /// </summary> /// <param name="type"></param> /// <param name="activeType"></param> /// <param name="fight"></param> /// <param name="caster"></param> /// <param name="castInfos"></param> /// <param name="cell"></param> /// <param name="duration"></param> /// <param name="actionId"></param> /// <param name="canGoThrough"></param> /// <param name="canStack"></param> /// <param name="hide"></param> protected AbstractActivableObject(FightObstacleTypeEnum type, ActiveType activeType, AbstractFight fight, AbstractFighter caster, CastInfos castInfos, int cell, int duration, int actionId, bool canGoThrough, bool canStack, bool hide = false) { m_fight = fight; m_caster = caster; m_spellId = castInfos.SpellId; m_actionSpell = SpellManager.Instance.GetTemplate(castInfos.Value1); m_actionEffect = m_actionSpell.GetLevel(castInfos.Value2); Cell = fight.GetCell(cell); ObstacleType = type; ActivationType = activeType; CanGoThrough = canGoThrough; CanStack = canStack; Color = castInfos.Value3; Targets = new List <AbstractFighter>(); Length = Pathfinding.GetDirection(castInfos.RangeType[1]); AffectedCells = new List <FightCell>(); Duration = duration; ActionId = actionId; Hide = hide; foreach (var effect in m_actionEffect.Effects) { if (CastInfos.IsDamageEffect(effect.TypeEnum)) { Priority--; } } // On ajout l'objet a toutes les cells qu'il affecte foreach (var cellId in CellZone.GetCircleCells(fight.Map, cell, Length)) { var fightCell = m_fight.GetCell(cellId); if (fightCell != null) { fightCell.AddObject(this); AffectedCells.Add(fightCell); } } if (Hide) { Appear(caster.Team); } else { AppearForAll(); } }
public override AIActionResult Execute() { switch (AttackState) { case AttackStateEnum.STATE_CALCULATE_CELLS: CastCellList = new Dictionary <int, List <SpellLevel> >(); WeakestEnnemies = Fighter.Team.OpponentTeam.AliveFighters.OrderBy(fighter => Pathfinding.GoalDistance(Map, Fighter.Cell.Id, fighter.Cell.Id)); foreach (var spellLevel in Fighter.SpellBook.GetSpells()) { foreach (var castCell in CellZone.GetCircleCells(Map, Fighter.Cell.Id, spellLevel.MaxPO)) { if (Fight.CanLaunchSpell(Fighter, spellLevel, spellLevel.SpellId, Fighter.Cell.Id, castCell) == FightSpellLaunchResultEnum.RESULT_OK) { if (!CastCellList.ContainsKey(castCell)) { CastCellList.Add(castCell, new List <SpellLevel>()); } CastCellList[castCell].Add(spellLevel); } } } if (CastCellList.Count == 0) { return(AIActionResult.FAILURE); } AttackState = AttackStateEnum.STATE_CALCULATE_EFFECT_TARGETS; return(AIActionResult.RUNNING); case AttackStateEnum.STATE_CALCULATE_EFFECT_TARGETS: TargetList = new Dictionary <int, Dictionary <int, Dictionary <SpellEffect, List <AbstractFighter> > > >(); foreach (var castInfos in CastCellList) { var castCell = castInfos.Key; TargetList.Add(castCell, new Dictionary <int, Dictionary <SpellEffect, List <AbstractFighter> > >()); foreach (var spellLevel in castInfos.Value) { if (spellLevel == null || spellLevel.Effects == null) { continue; } TargetList[castCell].Add(spellLevel.SpellId, new Dictionary <SpellEffect, List <AbstractFighter> >()); int effectIndex = 0; foreach (var effect in spellLevel.Effects) { TargetList[castCell][spellLevel.SpellId].Add(effect, new List <AbstractFighter>()); var targetType = spellLevel.Template.Targets != null ? spellLevel.Template.Targets.Count > effectIndex ? spellLevel.Template.Targets[effectIndex] : -1 : -1; if (effect.TypeEnum != EffectEnum.UseGlyph && effect.TypeEnum != EffectEnum.UseTrap) { foreach (var currentCellId in CellZone.GetCells(Map, castCell, Fighter.Cell.Id, spellLevel.RangeType)) { var fightCell = Fight.GetCell(currentCellId); if (fightCell != null) { foreach (var fighterObject in fightCell.FightObjects.OfType <AbstractFighter>()) { if (targetType != -1) { if (((((targetType >> 5) & 1) == 1) && (Fighter.Id != fighterObject.Id))) { if (!TargetList[castCell][spellLevel.SpellId][effect].Contains(Fighter)) { TargetList[castCell][spellLevel.SpellId][effect].Add(Fighter); } continue; } if (((targetType & 1) == 1) && Fighter.Team == fighterObject.Team) { continue; } if ((((targetType >> 1) & 1) == 1) && Fighter == fighterObject) { continue; } if ((((targetType >> 2) & 1) == 1) && Fighter.Team != fighterObject.Team) { continue; } if (((((targetType >> 3) & 1) == 1) && (fighterObject.Invocator == null))) { continue; } if (((((targetType >> 4) & 1) == 1) && (fighterObject.Invocator != null))) { continue; } } if (!TargetList[castCell][spellLevel.SpellId][effect].Contains(fighterObject)) { TargetList[castCell][spellLevel.SpellId][effect].Add(fighterObject); } } } } } effectIndex++; } } } AttackState = AttackStateEnum.STATE_CALCULATE_BEST_SPELL; return(AIActionResult.RUNNING); case AttackStateEnum.STATE_CALCULATE_BEST_SPELL: int bestScore = 0; foreach (var target in TargetList) { var castCell = target.Key; foreach (var spell in target.Value) { var spellId = spell.Key; var currentScore = -1; foreach (var levelInfos in spell.Value) { var effect = levelInfos.Key; foreach (var fighter in levelInfos.Value) { if (CastInfos.IsDamageEffect(effect.TypeEnum)) { if (fighter.Team.Id != Fighter.Team.Id) { currentScore += 200 + effect.Value1 + effect.Value2 + effect.Value3; } else { currentScore -= 200 + effect.Value1 + effect.Value2 + effect.Value3; } } else if (CastInfos.IsMalusEffect(effect.TypeEnum)) { if (fighter.Team.Id != Fighter.Team.Id) { currentScore += 45; } else { currentScore -= 45 + effect.Value1 + effect.Value2 + effect.Value3; } } else if (CastInfos.IsBonusEffect(effect.TypeEnum) || CastInfos.IsFriendlyEffect(effect.TypeEnum)) { if (fighter.Team.Id != Fighter.Team.Id) { currentScore -= 50 + effect.Value1 + effect.Value2 + effect.Value3; } else if (effect.TypeEnum == EffectEnum.Heal) { currentScore += 50 + (effect.Value1 + effect.Value2 + effect.Value3) * (100 - (int)((double)fighter.Life / fighter.MaxLife)); } else { currentScore += 50 + effect.Value1 + effect.Value2 + effect.Value3; } } } if (levelInfos.Value.Count == 0) { switch (effect.TypeEnum) { case EffectEnum.UseTrap: case EffectEnum.UseGlyph: case EffectEnum.Teleport: foreach (var ennemy in WeakestEnnemies) { currentScore += 50; currentScore -= Pathfinding.GoalDistance(Map, castCell, ennemy.Cell.Id); } break; case EffectEnum.Invocation: case EffectEnum.InvocationStatic: case EffectEnum.InvocDouble: currentScore += 50; break; } } } if (currentScore > bestScore) { bestScore = currentScore; SpellId = spellId; TargetCell = castCell; } } } if (SpellId == 0) { return(AIActionResult.FAILURE); } AttackState = AttackStateEnum.STATE_LAUNCH_ATTACK; return(AIActionResult.RUNNING); case AttackStateEnum.STATE_LAUNCH_ATTACK: Fight.TryLaunchSpell(Fighter, SpellId, TargetCell, 1000); Timeout = 1000; AttackState = AttackStateEnum.STATE_ATTACKING; return(AIActionResult.RUNNING); case AttackStateEnum.STATE_ATTACKING: if (!Timedout) { return(AIActionResult.RUNNING); } return(Initialize()); default: throw new Exception("AI Attack action invalid state."); } }