Пример #1
0
  public TaskAttack(Direction dir) {
    if (!Global.CanMoveDiagonal && !dir.isCardinal()) {
      throw new RuntimeException("Invalid attack direction: " + dir.toString());
    }

    this.dir = dir;
  }
Пример #2
0
  @Override
  public void processTask(GameEntity obj) {
    // Collect data
    GameTile oldTile = obj.tile[0][0];

    int newX = oldTile.x + dir.getX();
    int newY = oldTile.y + dir.getY();

    GameTile newTile = oldTile.level.getGameTile(newX, newY);

    Item wep = obj.getInventory().getEquip(EquipmentSlot.WEAPON);

    Array<GameTile> hitTiles = buildHitTileArray(obj, dir);

    // Check if should attack something
    boolean hitSomething = false;
    for (GameTile tile : hitTiles) {
      if (tile.entity != null && !tile.entity.isAllies(obj)) {
        hitSomething = true;
        break;
      }

      if (tile.environmentEntity != null
          && tile.environmentEntity.canTakeDamage
          && !tile.environmentEntity.passableBy.intersect(obj.getTravelType())) {
        hitSomething = true;
      }
    }

    // Do attack
    if (hitSomething) {
      doAttack(hitTiles, obj, wep);

      // do graphics stuff
      obj.sprite.spriteAnimation = new BumpAnimation(0.1f, dir);
    }
  }
Пример #3
0
  public static Array<Point> buildAllDirectionHitTiles(GameEntity entity) {
    Array<Point> points = new Array<Point>();

    Item weapon = entity.getInventory().getEquip(EquipmentSlot.WEAPON);

    for (Direction dir : Direction.values()) {
      if (Global.CanMoveDiagonal || dir.isCardinal()) {
        int xstep = 0;
        int ystep = 0;

        int sx = 0;
        int sy = 0;

        if (dir == Direction.NORTH) {
          sx = 0;
          sy = entity.size - 1;

          xstep = 1;
          ystep = 0;
        } else if (dir == Direction.SOUTH) {
          sx = 0;
          sy = 0;

          xstep = 1;
          ystep = 0;
        } else if (dir == Direction.EAST) {
          sx = entity.size - 1;
          sy = 0;

          xstep = 0;
          ystep = 1;
        } else if (dir == Direction.WEST) {
          sx = 0;
          sy = 0;

          xstep = 0;
          ystep = 1;
        }

        for (int i = 0; i < entity.size; i++) {
          GameTile attackerTile = entity.tile[sx + xstep * i][sy + ystep * i];

          if (weapon != null && weapon.wepDef != null) {
            Matrix3 mat = new Matrix3();
            mat.setToRotation(dir.getAngle());
            Vector3 vec = new Vector3();

            for (Point point : weapon.wepDef.hitPoints) {
              vec.set(point.x, point.y, 0);
              vec.mul(mat);

              int dx = Math.round(vec.x);
              int dy = Math.round(vec.y);

              Point pos = Global.PointPool.obtain().set(attackerTile.x + dx, attackerTile.y + dy);
              points.add(pos);
            }
          } else {
            Point pos =
                Global.PointPool.obtain()
                    .set(attackerTile.x + dir.getX(), attackerTile.y + dir.getY());
            points.add(pos);
          }
        }
      }
    }

    // restrict by visibility and remove duplicates
    Array<Point> visibleTiles = entity.visibilityCache.getCurrentShadowCast();

    Iterator<Point> itr = points.iterator();
    while (itr.hasNext()) {
      Point pos = itr.next();

      boolean matchFound = false;

      // Remove not visible
      for (Point point : visibleTiles) {
        if (point.x == pos.x && point.y == pos.y) {
          matchFound = true;
          break;
        }
      }

      // Remove duplicates
      for (int i = 0; i < points.size; i++) {
        Point opos = points.get(i);
        if (opos != pos && opos.x == pos.x && opos.y == pos.y) {
          matchFound = false;
          break;
        }
      }

      if (!matchFound) {
        itr.remove();

        Global.PointPool.free(pos);
      }
    }

    return points;
  }
Пример #4
0
  private void doAttack(Array<GameTile> hitTiles, final GameEntity entity, Item weapon) {
    final GameTile source = entity.tile[0][0];

    // Get all the attacked tiles
    Array<GameTile> attackedTiles = new Array<GameTile>();

    if (weapon == null
        || weapon.wepDef == null
        || weapon.wepDef.hitType == Item.WeaponDefinition.HitType.ALL) {
      attackedTiles.addAll(hitTiles);
    } else if (weapon.wepDef.hitType == Item.WeaponDefinition.HitType.CLOSEST) {
      int num = weapon.wepDef.hitData != null ? Integer.parseInt(weapon.wepDef.hitData) : 1;

      Array<GameTile> validEntityTiles = new Array<GameTile>();
      Array<GameTile> validEnvironmentTiles = new Array<GameTile>();

      // Get tiles valid to hit
      for (GameTile tile : hitTiles) {
        if (tile.entity != null && !tile.entity.isAllies(entity)) {
          validEntityTiles.add(tile);
        } else if (tile.environmentEntity != null && tile.environmentEntity.canTakeDamage) {
          validEnvironmentTiles.add(tile);
        }
      }

      Comparator<GameTile> comp =
          new Comparator<GameTile>() {
            @Override
            public int compare(GameTile o1, GameTile o2) {
              int dist1 = Math.abs(o1.x - source.x) + Math.abs(o1.y - source.y);
              int dist2 = Math.abs(o2.x - source.x) + Math.abs(o2.y - source.y);

              return dist1 - dist2;
            }
          };

      // sort by distance
      validEntityTiles.sort(comp);
      validEnvironmentTiles.sort(comp);

      for (int i = 0; i < num && i < validEntityTiles.size; i++) {
        attackedTiles.add(validEntityTiles.get(i));
      }

      for (int i = 0; i < num - validEntityTiles.size && i < validEnvironmentTiles.size; i++) {
        attackedTiles.add(validEnvironmentTiles.get(i));
      }
    } else if (weapon.wepDef.hitType == Item.WeaponDefinition.HitType.RANDOM) {
      int num = weapon.wepDef.hitData != null ? Integer.parseInt(weapon.wepDef.hitData) : 1;

      Array<GameTile> validEntityTiles = new Array<GameTile>();
      Array<GameTile> validEnvironmentTiles = new Array<GameTile>();

      // Get tiles valid to hit
      for (GameTile tile : hitTiles) {
        if (tile.entity != null && !tile.entity.isAllies(entity)) {
          validEntityTiles.add(tile);
        } else if (tile.environmentEntity != null && tile.environmentEntity.canTakeDamage) {
          validEnvironmentTiles.add(tile);
        }
      }

      if (validEntityTiles.size > 0) {
        for (int i = 0; i < num; i++) {
          attackedTiles.add(validEntityTiles.random());
        }
      } else if (validEnvironmentTiles.size > 0) {
        for (int i = 0; i < num; i++) {
          attackedTiles.add(validEnvironmentTiles.random());
        }
      }
    }

    Sprite hitEffect = null;
    if (weapon == null) {
      hitEffect = entity.defaultHitEffect;
    } else {
      hitEffect = weapon.getWeaponHitEffect();
    }

    Point minPoint = Global.PointPool.obtain().set(Integer.MAX_VALUE, Integer.MAX_VALUE);
    Point maxPoint = Global.PointPool.obtain().set(0, 0);

    int hitCount = weapon != null && weapon.wepDef != null ? weapon.wepDef.hitCount : 1;
    float animdelay = 0;

    for (int i = 0; i < hitCount; i++) {
      // Do the attack
      for (GameTile tile : attackedTiles) {
        // do misses
        int hitPercent = weapon != null && weapon.wepDef != null ? weapon.wepDef.hitPercent : 100;
        if (hitPercent < 100) {
          if (MathUtils.random(100) > hitPercent) {
            // Argh! a miss! Hit a random surrounding tile

            Direction dir = Direction.values()[MathUtils.random(Direction.values().length - 1)];
            GameTile newTile = tile.level.getGameTile(tile.x + dir.getX(), tile.y + dir.getY());
            if (newTile != null) {
              tile = newTile;
            }
          }
        }

        if (weapon == null
            || weapon.wepDef == null
            || weapon.wepDef.hitType != Item.WeaponDefinition.HitType.ALL) {
          int[] diff = tile.getPosDiff(source);

          Sprite sprite = hitEffect.copy();

          if (sprite.spriteAnimation != null) {
            int distMoved = (Math.abs(diff[0]) + Math.abs(diff[1])) / Global.TileSize;
            sprite.spriteAnimation.set(0.05f * distMoved, diff);
          }

          Vector2 vec = new Vector2(diff[0] * -1, diff[1] * -1);
          vec.nor();
          float x = vec.x;
          float y = vec.y;
          double dot = 0 * x + 1 * y; // dot product
          double det = 0 * y - 1 * x; // determinant
          float angle = (float) Math.atan2(det, dot) * MathUtils.radiansToDegrees;
          sprite.rotation = angle;

          sprite.renderDelay = animdelay;
          animdelay += 0.1f;

          boolean isMoving =
              sprite.spriteAnimation != null && sprite.spriteAnimation instanceof MoveAnimation;
          final SoundInstance sound = hitEffect.sound;

          final GameTile hitTile = tile;
          final GameEntity hitEntity = hitTile.entity;
          final EnvironmentEntity hitEnvEntity = hitTile.environmentEntity;

          sprite.spriteAction =
              new SpriteAction(
                  isMoving ? SpriteAction.FirePoint.End : SpriteAction.FirePoint.Start) {
                @Override
                public void evaluate() {
                  // do on hit
                  for (GameEventHandler handler : entity.getAllHandlers()) {
                    handler.onHit(entity, hitTile);
                  }

                  if (hitEntity != null && !hitEntity.isAllies(entity)) {
                    entity.attack(hitEntity, dir);
                  } else if (hitEnvEntity != null
                      && !hitEnvEntity.passableBy.intersect(entity.getTravelType())) {
                    entity.attack(hitEnvEntity, dir);
                  }

                  if (sound != null) {
                    sound.play(hitTile);
                  }
                }
              };

          SpriteEffect effect =
              new SpriteEffect(
                  sprite,
                  Direction.CENTER,
                  weapon != null && weapon.light != null ? weapon.light.copyNoFlag() : null);
          tile.spriteEffects.add(effect);
        } else {
          // do on hit
          for (GameEventHandler handler : entity.getAllHandlers()) {
            handler.onHit(entity, tile);
          }

          if (tile.entity != null && !tile.entity.isAllies(entity)) {
            entity.attack(tile.entity, dir);
          } else if (tile.environmentEntity != null
              && !tile.environmentEntity.passableBy.intersect(entity.getTravelType())) {
            entity.attack(tile.environmentEntity, dir);
          }

          if (tile.x < minPoint.x) {
            minPoint.x = tile.x;
          }
          if (tile.x > maxPoint.x) {
            maxPoint.x = tile.x;
          }
          if (tile.y < minPoint.y) {
            minPoint.y = tile.y;
          }
          if (tile.y > maxPoint.y) {
            maxPoint.y = tile.y;
          }
        }
      }
    }

    if (weapon != null
        && weapon.wepDef != null
        && weapon.wepDef.hitType == Item.WeaponDefinition.HitType.ALL) {
      // Use a joined sprite

      Sprite sprite = hitEffect.copy();

      sprite.rotation = dir.getAngle();
      sprite.baseScale[0] = (maxPoint.x - minPoint.x) + 1;
      sprite.baseScale[1] = (maxPoint.y - minPoint.y) + 1;

      if (dir == Direction.WEST || dir == Direction.EAST) {
        float temp = sprite.baseScale[0];
        sprite.baseScale[0] = sprite.baseScale[1];
        sprite.baseScale[1] = temp;
      }

      SpriteEffect effect =
          new SpriteEffect(
              sprite,
              Direction.CENTER,
              weapon != null && weapon.light != null ? weapon.light.copyNoFlag() : null);

      int px = minPoint.x;
      int py = minPoint.y;

      float dx = (maxPoint.x - minPoint.x) / 2.0f;
      float dy = (maxPoint.y - minPoint.y) / 2.0f;

      px += dir.getX() < 0 ? Math.ceil(dx) : Math.floor(dx);
      py += dir.getY() < 0 ? Math.ceil(dy) : Math.floor(dy);

      GameTile tile = attackedTiles.first().level.getGameTile(px, py);

      tile.spriteEffects.add(effect);

      SoundInstance sound = hitEffect.sound;
      if (sound != null) {
        sound.play(tile);
      }
    }
  }
Пример #5
0
  public static Array<GameTile> buildHitTileArray(GameEntity attacker, Direction dir) {
    Array<GameTile> tiles = new Array<GameTile>();

    Item weapon = attacker.getInventory().getEquip(EquipmentSlot.WEAPON);

    int xstep = 0;
    int ystep = 0;

    int sx = 0;
    int sy = 0;

    if (dir == Direction.NORTH) {
      sx = 0;
      sy = attacker.size - 1;

      xstep = 1;
      ystep = 0;
    } else if (dir == Direction.SOUTH) {
      sx = 0;
      sy = 0;

      xstep = 1;
      ystep = 0;
    } else if (dir == Direction.EAST) {
      sx = attacker.size - 1;
      sy = 0;

      xstep = 0;
      ystep = 1;
    } else if (dir == Direction.WEST) {
      sx = 0;
      sy = 0;

      xstep = 0;
      ystep = 1;
    }

    for (int i = 0; i < attacker.size; i++) {
      GameTile attackerTile = attacker.tile[sx + xstep * i][sy + ystep * i];

      if (weapon != null && weapon.wepDef != null) {
        Matrix3 mat = new Matrix3();
        mat.setToRotation(dir.getAngle());
        Vector3 vec = new Vector3();

        for (Point point : weapon.wepDef.hitPoints) {
          vec.set(point.x, point.y, 0);
          vec.mul(mat);

          int dx = Math.round(vec.x);
          int dy = Math.round(vec.y);

          GameTile tile = attackerTile.level.getGameTile(attackerTile.x + dx, attackerTile.y + dy);

          if (tile != null) {
            tiles.add(tile);
          }
        }
      } else {
        tiles.add(
            attackerTile.level.getGameTile(
                attackerTile.x + dir.getX(), attackerTile.y + dir.getY()));
      }
    }

    // restrict by visibility and remove duplicates
    Array<Point> visibleTiles = attacker.visibilityCache.getCurrentShadowCast();

    Iterator<GameTile> itr = tiles.iterator();
    while (itr.hasNext()) {
      GameTile tile = itr.next();

      boolean matchFound = false;

      // Remove not visible
      for (Point point : visibleTiles) {
        if (point.x == tile.x && point.y == tile.y) {
          matchFound = true;
          break;
        }
      }

      // Remove duplicates
      for (int i = 0; i < tiles.size; i++) {
        GameTile otile = tiles.get(i);
        if (otile != tile && otile.x == tile.x && otile.y == tile.y) {
          matchFound = false;
          break;
        }
      }

      if (!matchFound) {
        itr.remove();
      }
    }

    return tiles;
  }