/// <summary> /// Creates contestant agent that will perform planned actions /// </summary> private AIAgent CreateConstestantAgent(HumanoidContestant contestant) { AIAgent agent = new AIAgent(); agent.worldState["has usable skills"] = GetContestantUsableSkills(contestant).Count > 0; agent.goalState["hit target"] = true; return(agent); }
/// <summary> /// Find all contestant usable skills /// </summary> private List <Skill> GetContestantUsableSkills(HumanoidContestant contestant) { List <Skill> usableSkills = contestant.GetStanceUsableSkills(); usableSkills.RemoveAll(s => s.actionPointCost > contestant.ActionPoints || s.IsCoolingDown()); return(usableSkills); }
/// <summary> /// Display target zone on the arena prespective grid /// </summary> public void ShowTargetZone(HumanoidContestant actor, Color playerColor, Skill skill = null) { Vector2Int actorGridPosition = GetSpotGridPositionNew(actor.teamNumber, actor.spotNumber); // x = row, y = column int[,] targetZone = GetContestantTargetZone(actor, skill); ShowTargetZone(actorGridPosition, targetZone, playerColor); }
/// <summary> /// Returns all reachable targets for specific contestant based on his skill/weapon target zones /// </summary> public List <ContestantBody> GetContestantTargetZoneTargets(HumanoidContestant actor, Weapon weapon, Skill skill) { List <ContestantBody> resultTargets = new List <ContestantBody>(); int[,] targetZone = GetContestantTargetZone(actor, skill); Vector2Int gridSearchPosition = GetSpotGridPositionNew(actor.teamNumber, actor.spotNumber); // x = row, y = column Vector2Int actorTargetZonePosition = GetActorTargetZoneLocalPosition(targetZone); Vector2Int searchRange = new Vector2Int(targetZone.GetLength(0), targetZone.GetLength(1)); //if (actor.Fighter.fighterName == "Fronk Borin") { // Debug.Log("actorGridPosition: " + gridSearchPosition); // Debug.Log("actorTargetZoneLocation: " + actorTargetZonePosition); // Debug.Log("searchRange: " + searchRange); // Debug.Log("Fronk target zone"); // for (int row = 0; row < targetZone.GetLength(0); row++) { // string columnStr = string.Empty; // for (int column = 0; column < targetZone.GetLength(1); column++) { // columnStr += targetZone[row, column] + " "; // } // Debug.Log("row [" + row + "]: " + columnStr); // } //} Vector2Int anchoredGridSearchPosition = gridSearchPosition - actorTargetZonePosition; // top left anchor var targets = GetArenaGridContestants(anchoredGridSearchPosition, searchRange); for (int x = 0; x < targetZone.GetLength(0); x++) // rows { for (int y = 0; y < targetZone.GetLength(1); y++) // columns { int targetZoneValue = targetZone[x, y]; if (targets[x, y] == null) // Skip nulls { continue; } if (targetZoneValue == 1) // Skip player { continue; } // Pick only those of the opposite team if (targetZoneValue == 2 && targets[x, y].GetContestant().teamNumber != actor.teamNumber && !targets[x, y].GetContestant().isDead) { resultTargets.Add(targets[x, y]); } } } return(resultTargets); }
/// <summary> /// Get contestant modified flipped target zone combined wih weapon and skill /// </summary> /// <param name="actor"></param> /// <param name="skill"></param> /// <returns></returns> private int[,] GetContestantTargetZone(HumanoidContestant actor, Skill skill) { int[,] targetZone = actor.Weapon.targetZone; if (skill != null) { targetZone = CombineTargetZones(actor.Weapon.targetZone, skill.targetZone); } if (actor.teamNumber == 2) { targetZone = targetZone.FlipHorizontal(); } return(targetZone); }
/// <summary> /// Create contestant availible combat actions /// </summary> /// <param name="team"> current team </param> private List <AIAction> CreateContestantActions(HumanoidContestant contestant) { List <AIAction> actions = new List <AIAction>(); AIAction baseAttackAction = new AIAction(); baseAttackAction.name = "Base attack"; baseAttackAction.action = PerformContestantBaseAttackAction(contestant); baseAttackAction.cost = 1; baseAttackAction.effects["hit target"] = true; AIAction performSkillAction = new AIAction(); performSkillAction.name = "Perform skill"; performSkillAction.cost = 0; performSkillAction.preconditions["has usable skills"] = true; performSkillAction.effects["hit target"] = true; performSkillAction.action = PerformContestantSkillAction(contestant); actions.Add(baseAttackAction); actions.Add(performSkillAction); return(actions); }
/// <summary> /// With this action contestant will attack with weapon /// </summary> private IEnumerator PerformContestantBaseAttackAction(HumanoidContestant contestant) { contestant.portrait.HighlightPortrait(); List <ContestantBody> targets = FindContestantTargets(contestant, contestant.Weapon, null); if (targets.Count == 0) { //Debug.Log("<color=blue>" + contestant.fighter.fighterName + "</color> cannot perform action because he has no targets"); // Action cannot be performed contestant.portrait.UnhighlightPortrait(); yield break; } var animation = contestant.body.PlayWeaponAnimation(); while (animation.IsPlaying) { ArenaGrid.Instance.ShowTargetZone(contestant, Color.green); if (animation.DequeueEvent("impact")) { // Hit our targets foreach (var target in targets) { if (target == null || target.GetContestant().isDead) { continue; // skip if for some reason the target is dead or destroyed } //Debug.Log(contestant.fighter.fighterName + " damages " + t.GetFighter().fighterName + "with weapon"); HitData hit = new HitData(); hit.agressor = contestant.body; hit.incomingDamage = contestant.Weapon.attackDamage; hit.destination = target.GetHitLocation(); hit.hitTarget = target; hit.projectile = null; hit.skill = null; hit.sourceWeapon = contestant.Weapon; // Kinda send Hit event target.OnHit(hit); } } // Handle ranged weapons else if (animation.DequeueEvent("launch")) { foreach (var target in targets) { Projectile projectile = contestant.body.SpawnWeaponProjectile(); HitData projectileInstruction = new HitData(); projectileInstruction.agressor = contestant.body; projectileInstruction.incomingDamage = contestant.Weapon.attackDamage; projectileInstruction.destination = target.GetHitLocation(); projectileInstruction.hitTarget = target; projectileInstruction.projectile = projectile; projectileInstruction.skill = null; projectileInstruction.sourceWeapon = contestant.Weapon; projectile.Launch(projectileInstruction); } } yield return(null); } ArenaGrid.Instance.ResetGridCellsAppearance(); //UI.UIMatchManager.Instance.RefreshContestantPortraits(); contestant.portrait.UnhighlightPortrait(); }
/// <summary> /// Find all contestant targets /// </summary> private List <ContestantBody> FindContestantTargets(HumanoidContestant contestant, Weapon weapon, Skill skill) { return(ArenaGrid.Instance.GetContestantTargetZoneTargets(contestant, weapon, skill)); }
/// <summary> /// With this action contestant will attack with skill /// </summary> private IEnumerator PerformContestantSkillAction(HumanoidContestant contestant) { List <Skill> skills = GetContestantUsableSkills(contestant); Skill randomSkill = skills[Random.Range(0, skills.Count)]; contestant.portrait.HighlightPortrait(); contestant.portrait.HighlightSkill(randomSkill, true); List <ContestantBody> targets = FindContestantTargets(contestant, contestant.Weapon, randomSkill); if (targets.Count == 0) { // Action cannot be performed contestant.portrait.HighlightSkill(randomSkill, false); contestant.portrait.UnhighlightPortrait(); yield break; } contestant.ModifyActionPoints(-randomSkill.actionPointCost); randomSkill.ActivateCoolDown(); contestant.portrait.Refresh(); float incomingDamage = contestant.Weapon.attackDamage + Mathf.Abs(randomSkill.healthModifier); var animation = contestant.body.PlayWeaponAnimation(); while (animation.IsPlaying) { ArenaGrid.Instance.ShowTargetZone(contestant, Color.yellow, randomSkill); if (animation.DequeueEvent("impact")) { // Hit our targets foreach (var target in targets) { if (target == null || target.GetContestant().isDead) { continue; // skip if for some reason the target is dead or destroyed } HitData hit = new HitData(); hit.agressor = contestant.body; hit.incomingDamage = incomingDamage; hit.destination = target.GetHitLocation(); hit.hitTarget = target; hit.projectile = null; hit.skill = randomSkill; hit.sourceWeapon = contestant.Weapon; // Kinda send Hit event target.OnHit(hit); } } // Handle ranged weapons else if (animation.DequeueEvent("launch")) { foreach (var target in targets) { Projectile projectile = contestant.body.SpawnWeaponProjectile(); HitData projectileInstruction = new HitData(); projectileInstruction.agressor = contestant.body; projectileInstruction.incomingDamage = incomingDamage; projectileInstruction.destination = target.GetHitLocation(); projectileInstruction.hitTarget = target; projectileInstruction.projectile = projectile; projectileInstruction.skill = randomSkill; projectileInstruction.sourceWeapon = contestant.Weapon; projectile.Launch(projectileInstruction); } } yield return(null); } ArenaGrid.Instance.ResetGridCellsAppearance(); //UI.UIMatchManager.Instance.RefreshContestantPortraits(); contestant.portrait.HighlightSkill(randomSkill, false); contestant.portrait.UnhighlightPortrait(); }
public Vector3 GetSpotPosition(HumanoidContestant contestant) { return(GetSpotPosition(contestant.teamNumber, contestant.spotNumber)); }