示例#1
0
文件: Fight.java 项目: Neraloth/d2j
  public void useWeapon(final WeaponItem weapon, final IFighter caster, short targetCellId)
      throws FightException {
    final FightCell targetCell = cells[targetCellId];
    int distance =
        Pathfinding.distanceBetween(
            caster.getCurrentCell().getPosition(), targetCell.getPosition());

    if (caster.getStatistics().get(CharacteristicType.ActionPoints).getTotal()
        < weapon.getTemplate().getCost()) {
      throw new FightException("Invalid request: not enough AP.");
    } else if (distance < weapon.getTemplate().getMinRange()
        || distance > weapon.getTemplate().getMaxRange()) {
      throw new FightException("Invalid request: too close or to far from target.");
    } else {
      caster.getHandler().notifyRefreshStatistics();
      AppendableFightHandlerAction action =
          new AppendableFightHandlerAction(
              new FightHandlerAction() {
                @Override
                public void call(IFightHandler obj) throws FightException {
                  obj.notifyStartAction(caster.getId());
                }
              });

      boolean
          failure =
              FightUtils.computeFailure(weapon.getTemplate().getCriticalFailureRate(), caster),
          critical =
              !failure
                  && FightUtils.computeCritical(weapon.getTemplate().getCriticalRate(), caster);

      if (failure) {
        action.append(
            new FightHandlerAction() {
              @Override
              public void call(IFightHandler obj) throws FightException {
                obj.notifyBasicAction(ActionTypeEnum.SPELL_FAILURE, caster, 0);
              }
            });
      } else {
        action.append(
            new FightHandlerAction() {
              @Override
              public void call(IFightHandler obj) throws FightException {
                obj.notifyUseWeapon(caster, targetCell);
              }
            });

        if (critical) {
          action.append(
              new FightHandlerAction() {
                @Override
                public void call(IFightHandler obj) throws FightException {
                  obj.notifyBasicAction(ActionTypeEnum.SPELL_CRITICAL, caster, 0);
                }
              });
        }

        Collection<Effect> effects =
            critical ? weapon.getWeaponEffects() : weapon.getWeaponEffectsCritic();
        Collection<FightCell> targetCells =
            (critical ? weapon.getZone() : weapon.getCriticalZone())
                .filter(
                    caster.getCurrentCell(), targetCell, cells, map.getWidth(), map.getHeight());

        for (Effect effect : effects) {
          for (FightCell cell : targetCells) {
            effect.apply(action, caster, cell);
          }
        }
      }

      caster
          .getStatistics()
          .get(CharacteristicType.ActionPoints)
          .addContext((short) -weapon.getTemplate().getCost());

      action.append(
          new FightHandlerAction() {
            @Override
            public void call(IFightHandler obj) throws FightException {
              obj.notifyBasicAction(
                  ActionTypeEnum.AP_CHANGEMENT,
                  caster,
                  (int) caster.getId(),
                  -weapon.getTemplate().getCost());
              obj.notifyEndAction(EndActionTypeEnum.SPELL, caster);
            }
          });

      foreach(action);
    }
  }
示例#2
0
文件: Fight.java 项目: Neraloth/d2j
  public void castSpell(final Spell spell, final IFighter caster, short targetCellId, FightLog logs)
      throws FightException {
    final FightCell targetCell = cells[targetCellId];
    final ISpellLevel infos = spell.getInfos();
    final int distance =
        Pathfinding.distanceBetween(
            caster.getCurrentCell().getPosition(), targetCell.getPosition());

    if (caster.getStatistics().get(CharacteristicType.ActionPoints).getTotal() < infos.getCost()) {
      throw new SpellException("Invalid request: not enough AP.");
    } else if (distance > infos.getMaxRange() || distance < infos.getMinRange()) {
      throw new SpellException("Invalid request: you're too close or too far from the target.");
    } else if (caster.getLogs().castBySpell(spell.getTemplate()).size() > infos.getMaxPerTurn()) {
      throw new SpellException("Invalid request: too many cast of this spell.");
    } else {
      caster.getHandler().notifyRefreshStatistics();
      AppendableFightHandlerAction action =
          new AppendableFightHandlerAction(
              new FightHandlerAction() {
                @Override
                public void call(IFightHandler obj) throws FightException {
                  obj.notifyStartAction(caster.getId());
                }
              });

      boolean failure = FightUtils.computeFailure(infos.getCriticalFailRate(), caster),
          critical =
              infos.getCriticalEffects().size() > 0
                  && !failure
                  && FightUtils.computeCritical(infos.getCriticRate(), caster);

      if (failure) {
        action.append(
            new FightHandlerAction() {
              @Override
              public void call(IFightHandler obj) throws FightException {
                obj.notifyBasicAction(
                    ActionTypeEnum.SPELL_FAILURE, caster, spell.getTemplate().getId());
              }
            });
      } else {
        action.append(
            new FightHandlerAction() {
              @Override
              public void call(IFightHandler obj) throws FightException {
                obj.notifyCastSpell(caster, spell, targetCell);
              }
            });

        if (critical) {
          action.append(
              new FightHandlerAction() {
                @Override
                public void call(IFightHandler obj) throws FightException {
                  obj.notifyBasicAction(
                      ActionTypeEnum.SPELL_CRITICAL, caster, spell.getTemplate().getId());
                }
              });
        }

        if (targetCell.getCurrentFighter() != null
            && caster
                    .getLogs()
                    .castBySpell(spell.getTemplate())
                    .castByTarget(targetCell.getCurrentFighter())
                    .size()
                > infos.getMaxPerPlayer()) {
          throw new SpellException(
              "Invalid request: too many cast of this spell on the same target.");
        }

        Collection<Effect> effects = critical ? infos.getCriticalEffects() : infos.getEffects();

        for (Effect effect : effects) {
          List<IFighter> alreadyApplied = new ArrayList<>();

          Collection<FightCell> targetCells =
              effect
                  .getZone()
                  .filter(
                      caster.getCurrentCell(), targetCell, cells, map.getWidth(), map.getHeight());

          for (FightCell cell : targetCells) {
            if (cell.getCurrentFighter() != null) {
              if (alreadyApplied.contains(cell.getCurrentFighter())) continue;
              alreadyApplied.add(cell.getCurrentFighter());
            }

            if (effect.getNbTurns() > 0) {
              if (cell.getCurrentFighter() != null) {
                if (!effect.getFilter().filter(caster, cell.getCurrentFighter())) continue;
                if (effect instanceof BuffMaker) {
                  cell.getCurrentFighter()
                      .getBuffs()
                      .add(((BuffMaker) effect).make(caster, cell.getCurrentFighter()));
                } else {
                  cell.getCurrentFighter()
                      .getBuffs()
                      .add(
                          new EffectContainerBuff(
                              caster, cell.getCurrentFighter(), spell.getTemplate(), effect));
                }
              } else {
                // todo: trap, glyph
              }
            } else {
              effect.apply(action, caster, cell);
            }
          }
        }

        if (targetCell.getCurrentFighter() != null) {
          logs.add(new FightLog.SpellCast(targetCell.getCurrentFighter(), spell.getTemplate()));
        }
      }

      caster
          .getStatistics()
          .get(CharacteristicType.ActionPoints)
          .addContext((short) -infos.getCost());

      action.append(
          new FightHandlerAction() {
            @Override
            public void call(IFightHandler obj) throws FightException {
              obj.notifyBasicAction(
                  ActionTypeEnum.AP_CHANGEMENT, caster, (int) caster.getId(), -infos.getCost());
              obj.notifyEndAction(EndActionTypeEnum.SPELL, caster);
            }
          });

      foreach(action);
    }
  }