Beispiel #1
0
    public bool Process()
    {
        if (Unit.Stats.Health <= 0)
        {
            return(false);
        }

        if (TargetUnit == Unit || !TargetUnit.IsAlive || !TargetUnit.IsLinked)
        {
            return(false);
        }

        if (!Unit.Interaction.CheckCanAttack(TargetUnit))
        {
            return(false);
        }

        // assume melee attack right now
        // check if in direct proximity
        if (Unit.Interaction.GetClosestDistanceTo(TargetUnit) <= Unit.Interaction.GetAttackRange() + 0.5f)
        {
            // in direct proximity!
            //
            Vector2i enemyCell   = TargetUnit.Interaction.GetClosestPointTo(Unit);
            int      angleNeeded = Unit.FaceCellPrecise(enemyCell.x, enemyCell.y);
            if (Unit.Angle != angleNeeded)
            {
                Unit.AddActions(new RotateAction(Unit, angleNeeded));
                return(true);
            }

            //
            //Debug.LogFormat("ID {0} ATTACKING", Unit.ID);
            int         damage = Random.Range(Unit.Stats.DamageMin, Unit.Stats.DamageMax);
            DamageFlags df     = Unit.GetDamageType();
            // we need to compare Option to set damage flags properly here
            Unit.AddActions(new AttackAction(Unit, TargetUnit, df, damage));
        }
        else
        {
            //Debug.LogFormat("ID {0} TRY WALK TO", Unit.ID);
            // make one step to the target.
            MoveState.TryWalkTo(Unit, TargetUnit.X, TargetUnit.Y, TargetUnit.Width, TargetUnit.Height, Unit.Interaction.GetAttackRange());
        }

        return(true);
    }
Beispiel #2
0
    // made static because it's also used by other actions
    public static bool TryWalkTo(MapUnit unit, int walkX, int walkY, int walkWidth, int walkHeight, float distance = 0)
    {
        // check if target is walkable for us (statically)
        if (distance < 0)
        {
            distance = 0;
        }

        // note: 0x0 = specific cell
        // more than 0x0 = unit
        // for now just call pathfinding here

        // try to pathfind
        Vector2i point = unit.DecideNextMove(walkX, walkY, walkWidth, walkHeight, distance);

        if (point == null)
        {
            return(false);
        }

        /*int sbd = 32;
         * if (sbd > path.Count) sbd = path.Count;
         * for (int i = 0; i < sbd; i++)
         * {
         *  if (!unit.Interaction.CheckWalkableForUnit(path[i].x, path[i].y, false))
         *  {
         *      // one of nodes in statically found path (up to 32 nodes ahead) is non-walkable.
         *      // here we try to build another path around it instead.
         *      // if it's not found, we continue to walk along the old path.
         *      List<Vector2i> path2 = null;
         *      int pnum = path.Count - 1;
         *      while (path2 == null && pnum >= 0)
         *      {
         *          path2 = unit.DecideNextMove(path[pnum].x, path[pnum].y, false, distance);
         *          pnum--;
         *      }
         *
         *      if (path2 != null)
         *          path = path2;
         *      else if (i == 0)
         *          return false; // next node is not walkable. this means we got right into a wall
         *
         *      break;
         *  }
         * }*/

        // if NEXT node is not walkable, we drop into idle state.
        if (unit.Interaction.CheckWalkableForUnit(point.x, point.y, false))
        {
            // next path node found
            // notify clients
            unit.AddActions(new MoveAction(unit, point.x, point.y), new RotateAction(unit, unit.FaceCell(point.x, point.y)));
            return(true);
        }

        return(false);
    }
Beispiel #3
0
    public bool Process()
    {
        if (Unit.Stats.Health <= 0)
        {
            return(false);
        }

        if (TargetUnit == Unit || !TargetUnit.IsAlive || !MapLogic.Instance.Objects.Contains(TargetUnit))
        {
            return(false);
        }

        if (!Unit.Interaction.CheckCanAttack(TargetUnit))
        {
            return(false);
        }

        // assume melee attack right now
        // check if in direct proximity
        if (Unit.Interaction.GetClosestDistanceTo(TargetUnit) <= Unit.Interaction.GetAttackRange() + 0.5f)
        {
            // in direct proximity!
            //
            Vector2i enemyCell   = TargetUnit.Interaction.GetClosestPointTo(Unit);
            int      angleNeeded = Unit.FaceCellPrecise(enemyCell.x, enemyCell.y);
            if (Unit.Angle != angleNeeded)
            {
                Unit.AddActions(new RotateAction(Unit, angleNeeded));
                return(true);
            }

            //
            //Debug.LogFormat("ATTACKING");
            int damage = UnityEngine.Random.Range(Unit.Stats.DamageMin, Unit.Stats.DamageMax);
            Unit.AddActions(new AttackAction(Unit, TargetUnit, DamageFlags.Raw, damage));
        }
        else
        {
            // make one step to the target.
            MoveState.TryWalkTo(Unit, TargetUnit.X, TargetUnit.Y);
        }

        return(true);
    }
Beispiel #4
0
    public bool TryWalkTo(MapUnit unit, int walkX, int walkY, int walkWidth, int walkHeight, float distance = 0)
    {
        // check if we should not search yet
        if (LastBadPath > LastGoodPath && LastBadPath + RandomOffset > MapLogic.Instance.LevelTime)
        {
            return(false); // don't check for some time after bad path
        }
        // check if target is walkable for us (statically)
        if (distance < 0)
        {
            distance = 0;
        }

        // note: 0x0 = specific cell
        // more than 0x0 = unit
        // for now just call pathfinding here

        LastBadPath = MapLogic.Instance.LevelTime;

        // try to pathfind
        Vector2i point = unit.DecideNextMove(walkX, walkY, walkWidth, walkHeight, distance);

        if (point == null)
        {
            return(false);
        }

        // if NEXT node is not walkable, we drop into idle state.
        if (unit.Interaction.CheckWalkableForUnit(point.x, point.y, false))
        {
            LastGoodPath = MapLogic.Instance.LevelTime;
            // next path node found
            // notify clients
            unit.AddActions(new MoveAction(unit, point.x, point.y), new RotateAction(unit, unit.FaceCell(point.x, point.y)));
            return(true);
        }

        return(false);
    }
Beispiel #5
0
    public bool Process()
    {
        if (Unit.Stats.Health <= 0)
        {
            return(true);
        }

        bool doFullAI = (Unit.Player.Flags & PlayerFlags.AI) != 0 &&
                        (Unit.Player.Flags & PlayerFlags.Dormant) == 0;

        if (!doFullAI)
        {
            return(true);
        }
        // rotate randomly
        if ((UnityEngine.Random.Range(0, 256) < 1) &&
            Unit.Actions.Count == 1) // unit is idle and 1/256 chance returns true
        {
            int angle = UnityEngine.Random.Range(0, 36) * 10;
            Unit.AddActions(new RotateAction(Unit, angle));
        }

        return(true);
    }
Beispiel #6
0
    // made static because it's also used by other actions
    public static bool TryWalkTo(MapUnit unit, int walkX, int walkY)
    {
        // check if target is walkable for us (statically)
        if (!unit.Interaction.CheckWalkableForUnit(walkX, walkY, false))
        {
            List <Vector2i> switchNodes = new List <Vector2i>();
            for (int ly = walkY - unit.Height; ly < walkY + unit.Height; ly++)
            {
                for (int lx = walkX - unit.Width; lx < walkX + unit.Width; lx++)
                {
                    if (unit.Interaction.CheckWalkableForUnit(lx, ly, false))
                    {
                        switchNodes.Add(new Vector2i(lx, ly));
                    }
                }
            }

            switchNodes.Sort((a, b) =>
            {
                Vector2i own1 = unit.Interaction.GetClosestPointTo(a.x, a.y);
                Vector2i own2 = unit.Interaction.GetClosestPointTo(b.x, b.y);
                float d1      = (a - own1).magnitude;
                float d2      = (b - own2).magnitude;
                if (d1 > d2)
                {
                    return(1);
                }
                else if (d1 < d2)
                {
                    return(-1);
                }
                return(0);
            });

            if (switchNodes.Count <= 0)
            {
                return(false);
            }

            walkX = switchNodes[0].x;
            walkY = switchNodes[0].y;
        }

        if (walkX == unit.X && walkY == unit.Y)
        {
            return(true);
        }

        // try to pathfind
        List <Vector2i> path = unit.DecideNextMove(walkX, walkY, true);

        if (path == null)
        {
            return(false);
        }

        int sbd = 32;

        if (sbd > path.Count)
        {
            sbd = path.Count;
        }
        for (int i = 0; i < sbd; i++)
        {
            if (!unit.Interaction.CheckWalkableForUnit(path[i].x, path[i].y, false))
            {
                // one of nodes in statically found path (up to 32 nodes ahead) is non-walkable.
                // here we try to build another path around it instead.
                // if it's not found, we continue to walk along the old path.
                List <Vector2i> path2 = null;
                int             pnum  = path.Count - 1;
                while (path2 == null && pnum >= 0)
                {
                    path2 = unit.DecideNextMove(path[pnum].x, path[pnum].y, false);
                    pnum--;
                }

                if (path2 != null)
                {
                    path = path2;
                }

                break;
            }
        }

        // if NEXT node is not walkable, we drop into idle state.
        if (unit.Interaction.CheckWalkableForUnit(path[0].x, path[0].y, false))
        {
            // next path node found
            // notify clients
            unit.AddActions(new MoveAction(unit, path[0].x, path[0].y), new RotateAction(unit, unit.FaceCell(path[0].x, path[0].y)));
            return(true);
        }

        return(false);
    }
Beispiel #7
0
    public bool Process()
    {
        if (Executed && Unit.Actions[Unit.Actions.Count - 1].GetType() != typeof(AttackAction))
        {
            return(false);
        }

        if (Unit.Stats.Health <= 0)
        {
            return(false);
        }

        if (TargetUnit == Unit || (TargetUnit != null && (!TargetUnit.IsAlive || !MapLogic.Instance.Objects.Contains(TargetUnit))))
        {
            return(false);
        }

        if (TargetUnit != null && !Unit.Interaction.CheckCanAttack(TargetUnit))
        {
            return(false);
        }

        // assume melee attack right now
        // check if in direct proximity
        if ((TargetUnit != null && Unit.Interaction.GetClosestDistanceTo(TargetUnit) <= Spell.GetDistance() + 0.5f) ||
            (TargetUnit == null && (Unit.Interaction.GetClosestPointTo(TargetX, TargetY) - new Vector2i(TargetX, TargetY)).magnitude <= Spell.GetDistance() + 0.5f))
        {
            // in direct proximity!
            //
            Vector2i enemyCell   = (TargetUnit != null ? TargetUnit.Interaction.GetClosestPointTo(Unit) : new Vector2i(TargetX, TargetY));
            int      angleNeeded = Unit.FaceCellPrecise(enemyCell.x, enemyCell.y);
            if (Unit.Angle != angleNeeded)
            {
                Unit.AddActions(new RotateAction(Unit, angleNeeded));
                return(true);
            }

            //
            //Debug.LogFormat("ATTACKING");
            if (Unit.Stats.Mana >= Spell.Template.ManaCost)
            {
                Unit.AddActions(new AttackAction(Unit, TargetUnit, Spell, TargetX, TargetY));
                Unit.Stats.TrySetMana(Unit.Stats.Mana - Spell.Template.ManaCost);
                Unit.DoUpdateView = true;
                Unit.DoUpdateInfo = true;
            }
            else
            {
                return(false); // :( no mana
            }
            Executed = true;
        }
        else
        {
            // make one step to the target.
            if (TargetUnit != null)
            {
                MoveState.TryWalkTo(Unit, TargetUnit.X, TargetUnit.Y);
            }
            else
            {
                MoveState.TryWalkTo(Unit, TargetX, TargetY);
            }
        }

        return(true);
    }
Beispiel #8
0
    public bool Process()
    {
        // check target. if target is outside map range, terminate. server doesn't really handle this well
        if (TargetX < 8 || TargetY < 8 || TargetX >= MapLogic.Instance.Width - 8 || TargetY >= MapLogic.Instance.Height - 8)
        {
            if (TargetUnit != null)
            {
                TargetX = -1;
                TargetY = -1;
            }
            else
            {
                return(false);
            }
        }

        if (Executed && Unit.Actions[Unit.Actions.Count - 1].GetType() != typeof(AttackAction))
        {
            return(false);
        }

        if (Unit.Stats.Health <= 0)
        {
            return(false);
        }

        if ((IsAttack && TargetUnit == Unit) || (TargetUnit != null && (!TargetUnit.IsAlive || !TargetUnit.IsLinked)))
        {
            return(false);
        }

        if (TargetUnit != null && !Unit.Interaction.CheckCanAttack(TargetUnit))
        {
            return(false);
        }

        // assume melee attack right now
        // check if in direct proximity
        if ((TargetUnit != null && Unit.Interaction.GetClosestDistanceTo(TargetUnit) <= Spell.GetDistance() + 0.5f) ||
            (TargetUnit == null && (Unit.Interaction.GetClosestPointTo(TargetX, TargetY) - new Vector2i(TargetX, TargetY)).magnitude <= Spell.GetDistance() + 0.5f))
        {
            // in direct proximity!
            //
            if (TargetUnit != Unit)
            {
                Vector2i enemyCell   = (TargetUnit != null ? TargetUnit.Interaction.GetClosestPointTo(Unit) : new Vector2i(TargetX, TargetY));
                int      angleNeeded = Unit.FaceCellPrecise(enemyCell.x, enemyCell.y);
                if (Unit.Angle != angleNeeded)
                {
                    Unit.AddActions(new RotateAction(Unit, angleNeeded));
                    return(true);
                }
            }

            //
            //Debug.LogFormat("ATTACKING");
            if ((Spell.Item != null || Unit.Stats.Mana >= Spell.Template.ManaCost) &&
                (!Spell.ItemDisposable || Unit.ItemsPack.Contains(Spell.Item)))
            {
                Unit.AddActions(new AttackAction(Unit, TargetUnit, Spell, TargetX, TargetY));
                if (Spell.Item == null && Unit.Stats.TrySetMana(Unit.Stats.Mana - Spell.Template.ManaCost) && NetworkManager.IsServer)
                {
                    Server.NotifyUnitStatsShort(Unit);
                }
                else if (Spell.Item != null && Spell.ItemDisposable && Unit.ItemsPack.TakeItem(Spell.Item, 1) != null)
                {
                    Server.NotifyUnitPack(Unit);
                }
                Unit.DoUpdateView = true;
                Unit.DoUpdateInfo = true;
            }
            else
            {
                return(false); // :( no mana
            }
            Executed = true;
        }
        else
        {
            // make one step to the target.
            if (TargetUnit != null)
            {
                MoveState.TryWalkTo(Unit, TargetUnit.X, TargetUnit.Y, TargetUnit.Width, TargetUnit.Height, Spell.GetDistance());
            }
            else
            {
                MoveState.TryWalkTo(Unit, TargetX, TargetY, 0, 0, Spell.GetDistance());
            }
        }

        return(true);
    }