Пример #1
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);
      }
    }
  }