public PartyTurnActor() { MoveAction moveAction = new MoveAction(m_activeActions); RotateAction rotateAction = new RotateAction(m_activeActions); RestAction restAction = new RestAction(); InteractAction interactAction = new InteractAction(); SelectNextInteractiveObjectAction selectNextInteractiveObjectAction = new SelectNextInteractiveObjectAction(); m_actions = new BaseAction[4][]; for (Int32 i = 0; i < m_actions.Length; i++) { m_actions[i] = new BaseAction[11]; m_actions[i][0] = moveAction; m_actions[i][1] = rotateAction; m_actions[i][6] = restAction; m_actions[i][2] = interactAction; m_actions[i][10] = selectNextInteractiveObjectAction; m_actions[i][3] = new MeleeAttackAction(i); m_actions[i][4] = new RangedAttackAction(i); m_actions[i][9] = new CastSpellAction(i); m_actions[i][5] = new ConsumeItemAction(i); m_actions[i][8] = new DefendAction(i); m_actions[i][7] = new EquipAction(i); } }
public override void FindNextState() { if (currentAction is WaitAction) { currentAction = new WalkAction(owner, TargetType.PLAYER); } else if (currentAction is WalkAction) { GameObject nearestPlayer = FindNearestPlayer(); if ((nearestPlayer.transform.position - owner.transform.position).sqrMagnitude <= Mathf.Pow(0.22f, 2f)) { currentAction = new AttackPrepareAction(owner, nearestPlayer, 0.4f); } } else if (currentAction is AttackPrepareAction) { if (currentAction.isOver) { AttackPrepareAction prevAction = currentAction as AttackPrepareAction; currentAction = new MeleeAttackAction(owner, prevAction.targetPosition, 1f, 2f); } } else if (currentAction is MeleeAttackAction) { if (currentAction.isOver) { owner.animator.SetTrigger("Idle"); currentAction = new WaitAction(); } } }
private List <EncounterAction> MoveAndAttack(EncounterState state, int dx, int dy) { var positionComponent = state.Player.GetComponent <PositionComponent>(); var oldPos = positionComponent.EncounterPosition; var newPos = new EncounterPosition(oldPos.X + dx, oldPos.Y + dy); // TODO: maybe not hostile? var hostiles = AIUtils.HostilesInPosition(state, FactionName.PLAYER, newPos.X, newPos.Y); if (hostiles.Count > 0) { var attackAction = new MeleeAttackAction(state.Player.EntityId, hostiles[state.EncounterRand.Next(hostiles.Count)]); return(new List <EncounterAction>() { attackAction }); } else { var moveAction = new MoveAction(state.Player.EntityId, newPos); return(new List <EncounterAction>() { moveAction }); } }
public Action GetAction(EntityMap entityMap, GroundMap groundMap) { Action action; var aStar = new AStar(groundMap, entityMap); var target = entityMap.GetPlayer(); var actionResult = new ActionResult(); if (target == null) { // If no target, the pathfinding doesn't know what to do, so wait instead and send a message up action = BuildWaitAction(actionResult, entityMap, groundMap); } // Right now enemies will only act if the player can see them else if (groundMap.isTileVisible(owner.position)) { // Attempt to move towards the AIs target (this doesn't have to be the player!) if (owner.DistanceTo(target) >= 2) { var moveTile = aStar.FindPathToTarget((owner.position.x, owner.position.y), (target.position.x, target.position.y)); if (moveTile == null) { // No path found I guess action = BuildWaitAction(actionResult, entityMap, groundMap); } else { action = new WalkAction(owner.actor, new CellPosition(moveTile.x, moveTile.y)); } } else { // If we're in melee range, attack instead of move if (owner.GetComponent <Fighter>() == null) { // Can't fight though... ha action = BuildWaitAction(actionResult, entityMap, groundMap); } else { action = new MeleeAttackAction(owner.actor, target.position); } } } else { // Nothing to do, not visible, just wait action = BuildWaitAction(actionResult, entityMap, groundMap, logMessage: false); } return(action); }
public void DoRoundOfCombat(List <Character.Character> characters) { RoundCount++; foreach (var character in TurnOrder) { CurrentCharacter = character; //TODO DetermineAction() AbstractAction chosenAction = new MeleeAttackAction(); //ToDO DetermineTarget() var target = characters.FirstOrDefault(x => x.Team != CurrentCharacter.Team); //simple for now. chosenAction.DoAction(CurrentCharacter, target); } }
private static bool ResolveMeleeAttack(MeleeAttackAction action, EncounterState state) { Entity attacker = state.GetEntityById(action.ActorId); Entity defender = action.TargetEntity; var attackerComponent = attacker.GetComponent <AttackerComponent>(); var attackerDefenderComponent = attacker.GetComponent <DefenderComponent>(); var defenderComponent = defender.GetComponent <DefenderComponent>(); if (defenderComponent.IsInvincible) { var logMessage = string.Format("[b]{0}[/b] hits [b]{1}[/b], but the attack has no effect!", attacker.EntityName, defender.EntityName); LogAttack(attacker, defender, defenderComponent, logMessage, state); } else { bool isPlayer = attacker == state.Player; bool hit = false; bool killed = false; var attackReport = AttackHits(state.EncounterRand, attackerComponent.MeleeAttack, attackerDefenderComponent.FootingPenalty, defenderComponent.MeleeDefense, defenderComponent.FootingPenalty); attackerDefenderComponent.NotifyParentHasAttacked(); if (!attackReport.Item3) { var logMessage = string.Format("[b]{0}[/b] attacks [b]{1}[/b], but misses! ({2}% chance to hit)", attacker.EntityName, defender.EntityName, attackReport.Item1); LogAttack(attacker, defender, defenderComponent, logMessage, state); return(true); } // We don't allow underflow damage, though that could be a pretty comical mechanic... int weaponDamage = Math.Max(0, attackerComponent.Power - defenderComponent.Defense); int shieldedByFooting = (int)Math.Floor(weaponDamage * defenderComponent.PercentageFooting); int hpDamage = weaponDamage - shieldedByFooting; int footingDamage = shieldedByFooting * 3; hit = true; defenderComponent.RemoveHp(hpDamage); defenderComponent.RemoveFooting(footingDamage); if (defenderComponent.CurrentHp <= 0) { killed = true; var logMessage = string.Format("[b]{0}[/b] hits [b]{1}[/b] for {2} damage, killing it! ({3}% chance to hit)", attacker.EntityName, defender.EntityName, hpDamage, attackReport.Item1); // Assign XP to the entity that fired the projectile var attackerId = state.GetEntityById(attackerComponent.SourceEntityId); var xpValueComponent = defender.GetComponent <XPValueComponent>(); if (attackerId != null && xpValueComponent != null && attackerId.GetComponent <XPTrackerComponent>() != null) { attackerId.GetComponent <XPTrackerComponent>().AddXP(xpValueComponent.XPValue, attackerComponent, defenderComponent, state); logMessage += String.Format(" [b]{0}[/b] gains {1} XP!", attackerId.EntityName, xpValueComponent.XPValue); } LogAttack(attacker, defender, defenderComponent, logMessage, state); ResolveAction(new DestroyAction(defender.EntityId), state); } else { var logMessage = string.Format("[b]{0}[/b] hits [b]{1}[/b] for {2} HP damage and {3} footing damage! ({4}% chance to hit)", attacker.EntityName, defender.EntityName, hpDamage, shieldedByFooting, attackReport.Item1); LogAttack(attacker, defender, defenderComponent, logMessage, state); } // Finally, assign player prestige if (isPlayer && killed) { var logMessage = string.Format("Your allies witness you slaying the [b]{0}[/b]. [b]You gain 5 prestige![/b]", defender.EntityName); attacker.GetComponent <PlayerComponent>().AddPrestige(5, state, logMessage, PrestigeSource.DEFEATING_FOES); } else if (isPlayer && hit) { var logMessage = string.Format("Your allies will remember that injured the [b]{0}[/b]. [b]You gain 1 prestige![/b]", defender.EntityName); attacker.GetComponent <PlayerComponent>().AddPrestige(1, state, logMessage, PrestigeSource.LANDING_HITS); } } return(true); }