public void PrintMoveMap(Movemap movemap, Node.TileGameStatus characterFraction) { foreach (var tilePosition in movemap.MoveCoords) { Movemap.SetTile(tilePosition, MoveTile); } foreach (var tilePosition in movemap.MeleeCoords) { if (GetNode(tilePosition).GameStatus == characterFraction) { Movemap.SetTile(tilePosition, AllyTile); } else { Movemap.SetTile(tilePosition, EnemyTile); } } foreach (var tilePosition in movemap.RangeCoords) { if (GetNode(tilePosition).GameStatus == characterFraction) { Movemap.SetTile(tilePosition, AllyTile); } else { Movemap.SetTile(tilePosition, EnemyTile); } } }
public void DefineAvailableMeleeTargets(Movemap movemap, Character currentCharacter, List <Character> characterList, List <Node.TileGameStatus> targetFractions, int attackDistance) { foreach (var character in characterList) { if (character.Properties.CurrentHealth <= 0 || character == currentCharacter || !targetFractions.Contains(Node.GetTileStatusFromCharacter(character))) { continue; } Vector3Int offsetCoords = character.Coords; //check all directions for (int i = 0; i < 4; ++i) { offsetCoords = character.Coords + attackDistance * offsets[i]; //if tile belongs to movemap and empty than character can attack target from it if (movemap.MoveCoords.IndexOf(offsetCoords) != -1) { movemap.MeleeCoords.Add(character.Coords); break; } } } }
public Movemap Copy() { Movemap newMovemap = new Movemap(); newMovemap.MoveCoords.AddRange(MoveCoords); newMovemap.MeleeCoords.AddRange(MeleeCoords); newMovemap.RangeCoords.AddRange(RangeCoords); return(newMovemap); }
public void PrintCharacterMoveMap(Character character, List <Character> characterList, int attackDistance) { Node.TileGameStatus fraction; fraction = Node.GetTileStatusFromCharacter(character); List <Node.TileGameStatus> fractionList = new List <Node.TileGameStatus>(); if (fraction == Node.TileGameStatus.Ally) { fractionList.Add(Node.TileGameStatus.Enemy); } else { fractionList.Add(Node.TileGameStatus.Ally); } _movemap = BuildMovemap(fraction, character.Properties.Speed, character.Coords); DefineAvailableMeleeTargets(_movemap, character, characterList, fractionList, attackDistance); PrintMoveMap(_movemap, fraction); }
public List <Vector3Int> DefinePositionsToAttackTarget(Movemap movemap, Character target, int attackDistance) { Vector3Int offsetCoords = target.Coords; List <Vector3Int> positions = new List <Vector3Int>(); //check all directions for (int i = 0; i < 4; ++i) { offsetCoords = target.Coords + attackDistance * offsets[i]; //if tile belongs to movemap and empty than character can attack from it if (movemap.MoveCoords.IndexOf(offsetCoords) != -1) { positions.Add(offsetCoords); } } return(positions); }
/* * Movemap section */ public Movemap BuildMovemap(Node.TileGameStatus fraction, int moveDistance, Vector3Int position) { Movemap map = new Movemap(); List <Node> nodesToProcess = new List <Node>(); Node currentNode = _graph.GetNode(position); if (currentNode.GameStatus == Node.TileGameStatus.Block) { return(map); } currentNode.ProcessValue = moveDistance; currentNode.ProcessStatus = Node.NodeProcessStatus.InOpenList; nodesToProcess.Add(currentNode); map.MoveCoords.Add(currentNode.Coords); while (nodesToProcess.Count != 0) { currentNode = nodesToProcess[0]; foreach (var connection in currentNode.Connections) { Node endNode = connection.EndNode; if ((endNode.ProcessStatus == Node.NodeProcessStatus.NotVisited || endNode.ProcessValue < currentNode.ProcessValue - 1) && endNode.GameStatus == Node.TileGameStatus.Empty) { //first entry in open list and not taken by characters if (endNode.ProcessStatus == Node.NodeProcessStatus.NotVisited) { map.MoveCoords.Add(endNode.Coords); } endNode.ProcessValue = currentNode.ProcessValue - 1; //if node has been already waiting processing in open list then change order if (endNode.ProcessStatus == Node.NodeProcessStatus.InOpenList) { nodesToProcess.Remove(endNode); } if (endNode.ProcessValue > 0) { int indexToInsert = nodesToProcess.FindLastIndex(delegate(Node node) { return(node.ProcessValue >= endNode.ProcessValue); }); nodesToProcess.Insert(indexToInsert, endNode); endNode.ProcessStatus = Node.NodeProcessStatus.InOpenList; } else { endNode.ProcessStatus = Node.NodeProcessStatus.InClosedList; } } } nodesToProcess.Remove(currentNode); currentNode.ProcessStatus = Node.NodeProcessStatus.InClosedList; } _graph.RestoreProcessStatus(); return(map); }
public void SetMovemap(Movemap movemap) { _movemap = movemap; }
//foreach possible decision pair it with target given by context //this is bad solution, because to create new qualifier we need to upgrade this method public void MakeDecisionsList(ContextBase context) { if (PossibleDecisions == null) { PossibleDecisions = new List <Decision>(); } PossibleDecisions.Clear(); for (int i = 0; i < Qualifiers.Count; ++i) { if (Qualifiers[i].Type == UtilityAISystem.Qualifiers.MeleeAttack) { for (int j = 0; j < context.AvailableMeleeTargets.Count; ++j) { Character target = GameController.Instance.FindCharacter(context.AvailableMeleeTargets[j]); //we need define from that side character can attack his target List <Vector3Int> possibleTilesToAttack = GridSystem.Instance.GetNearMovemapTilesList(target.Coords); if (GameController.Instance.IsCharactersStayNear(context.Provider.GetControlledCharacter(), target)) { possibleTilesToAttack.Add(context.Provider.GetControlledCharacter().Coords); } foreach (var coords in possibleTilesToAttack) { Decision decision = new Decision(); decision.Context = context.Copy(); decision.Context.Target = target; decision.Context.Data.Add("AttackTile", coords); decision.QualifierRef = Qualifiers[i]; PossibleDecisions.Add(decision); } } } else if (Qualifiers[i].Type == UtilityAISystem.Qualifiers.Move) { Character currentCharacter = context.Provider.GetControlledCharacter(); Movemap movemap = GridSystem.Instance.GetCurrentMovemap(); for (int j = 0; j < movemap.MoveCoords.Count; ++j) { if (movemap.MoveCoords[j] == currentCharacter.Coords) { continue; } Decision decision = new Decision(); decision.Context = context.Copy(); decision.Context.Target = movemap.MoveCoords[j]; decision.QualifierRef = Qualifiers[i]; PossibleDecisions.Add(decision); } } else if (Qualifiers[i].Type == UtilityAISystem.Qualifiers.RangedAttack) { for (int j = 0; j < context.AvailableRangedTargets.Count; ++j) { Character target = GameController.Instance.FindCharacter(context.AvailableRangedTargets[j]); Decision decision = new Decision(); decision.Context = context.Copy(); decision.Context.Target = target; decision.QualifierRef = Qualifiers[i]; PossibleDecisions.Add(decision); } } else if (Qualifiers[i].Type == UtilityAISystem.Qualifiers.Skill) { Character user = context.Provider.GetControlledCharacter(); Skill skill = user.Skills[Qualifiers[i].SkillNo]; if (skill.CurrentCooldown > 0 || skill.CurrentCount == 0) { continue; } if (skill.TypeTarget == Skill.TargetType.Self) { Decision decision = new Decision(); decision.Context = context.Copy(); decision.Context.Target = user; decision.Context.Data.Add("SkillNo", Qualifiers[i].SkillNo); decision.QualifierRef = Qualifiers[i]; PossibleDecisions.Add(decision); } else if (skill.TypeUse == Skill.UseType.Melee) { //define list of target fractions List <string> fractionList = new List <string>(); if (skill.FractionTarget == Skill.TargetFraction.Enemy) { fractionList.Add(user.GetOppositeFraction()); } else if (skill.FractionTarget == Skill.TargetFraction.Ally) { fractionList.Add(user.tag); } else { fractionList.Add(user.GetOppositeFraction()); fractionList.Add(user.tag); } //define all data Movemap skillMovemap = new Movemap(); skillMovemap.MoveCoords.AddRange(GridSystem.Instance.GetCurrentMovemap().MoveCoords); //define all target that character can reach GridSystem.Instance.DefineAvailableMeleeTargets(skillMovemap, user, GameController.Instance.CharacterList, GridSystem.ConvertFractionsFromStringToNode(fractionList), skill.Distance); //define all positions to attack for all targets List <List <Vector3Int> > possiblePositions = new List <List <Vector3Int> >(); for (int j = 0; j < skillMovemap.MeleeCoords.Count; ++j) { Character targetCharacter = GridSystem.Instance.GetCharacterFromCoords(skillMovemap.MeleeCoords[j]); //get possible positions to attack possiblePositions.Add(GridSystem.Instance.DefinePositionsToAttackTarget(skillMovemap, targetCharacter, skill.Distance)); //additional special checks skill.AdditionalChecks(targetCharacter, possiblePositions[j]); //if there no possible positions to attack than delete this target from list if (possiblePositions[j].Count == 0) { skillMovemap.MeleeCoords.RemoveAt(j); possiblePositions.RemoveAt(j); --j; } } //create decision to all pairs target-possible position for (int j = 0; j < skillMovemap.MeleeCoords.Count; ++j) { foreach (var coords in possiblePositions[j]) { Decision decision = new Decision(); decision.Context = context.Copy(); decision.Context.Target = GridSystem.Instance.GetCharacterFromCoords(skillMovemap.MeleeCoords[j]); decision.Context.Data.Add("AttackTile", coords); decision.Context.Data.Add("SkillNo", Qualifiers[i].SkillNo); decision.QualifierRef = Qualifiers[i]; PossibleDecisions.Add(decision); } } } else if (skill.TypeUse == Skill.UseType.Randged) { //define list of target fractions List <string> fractionList = new List <string>(); if (skill.FractionTarget == Skill.TargetFraction.Enemy) { fractionList.Add(user.GetOppositeFraction()); } else if (skill.FractionTarget == Skill.TargetFraction.Ally) { fractionList.Add(user.tag); } else { fractionList.Add(user.GetOppositeFraction()); fractionList.Add(user.tag); } Movemap skillMovemap = new Movemap(); bool isThereEnemyNearby = GameController.Instance.IsThereEnemyNearby(user); if ((isThereEnemyNearby && skill.UseNearEnemy) || (!isThereEnemyNearby && user.Properties.Class != CharacterClass.Archer)) { foreach (var fraction in fractionList) { skillMovemap.RangeCoords.AddRange(GameController.Instance.DefineAvailableRangedTargets(user, fraction)); } } else if (!isThereEnemyNearby && user.Properties.Class == CharacterClass.Archer) //this can reduce amount of raycasts { skillMovemap.RangeCoords.AddRange(GridSystem.Instance.GetCurrentMovemap().RangeCoords); if (fractionList.Contains(user.tag)) { skillMovemap.RangeCoords.AddRange(GameController.Instance.DefineAvailableRangedTargets(user, user.tag)); } } foreach (var targetCoords in skillMovemap.RangeCoords) { Decision decision = new Decision(); decision.Context = context.Copy(); decision.Context.Target = GridSystem.Instance.GetCharacterFromCoords(targetCoords); decision.Context.Data.Add("SkillNo", Qualifiers[i].SkillNo); decision.QualifierRef = Qualifiers[i]; PossibleDecisions.Add(decision); } } } } }