예제 #1
0
  public static Optional<List<Tuple<DamageModifier, Function<? super Double, Double>>>>
      createArmorModifiers(
          EntityLivingBase entityLivingBase, DamageSource damageSource, double damage) {
    if (!damageSource.isDamageAbsolute()) {
      damage *= 25;
      net.minecraft.item.ItemStack[] inventory =
          entityLivingBase instanceof EntityPlayer
              ? ((EntityPlayer) entityLivingBase).inventory.armorInventory
              : entityLivingBase.getInventory();
      List<Tuple<DamageModifier, Function<? super Double, Double>>> modifiers = new ArrayList<>();
      List<DamageObject> damageObjects = new ArrayList<>();
      for (int index = 0; index < inventory.length; index++) {
        net.minecraft.item.ItemStack itemStack = inventory[index];
        if (itemStack == null) {
          continue;
        }
        Item item = itemStack.getItem();
        if (item instanceof ItemArmor) {
          ItemArmor armor = (ItemArmor) item;
          double reduction = armor.damageReduceAmount / 25D;
          DamageObject object = new DamageObject();
          object.slot = index;
          object.ratio = reduction;
          damageObjects.add(object);
        }
      }
      boolean first = true;
      double ratio = 0;

      for (DamageObject prop : damageObjects) {
        EquipmentType type = resolveEquipment(prop.slot);

        final DamageObject object = new DamageObject();
        object.ratio = ratio;
        if (first) {
          object.previousDamage = damage;
          object.augment = true;
        }
        Function<? super Double, Double> function =
            incomingDamage -> {
              incomingDamage *= 25;
              if (object.augment) {
                // This is the damage that needs to be archived for the "first" armor modifier
                // function since the armor modifiers work based on the initial damage and not as
                // a chain one after another.
                damageToHandle = incomingDamage;
              }
              double functionDamage = damageToHandle;
              object.previousDamage = functionDamage;
              object.ratio = prop.ratio;
              object.ratio += prop.ratio;
              return -((functionDamage * prop.ratio) / 25);
            };
        ratio += prop.ratio;

        DamageModifier modifier =
            DamageModifier.builder()
                .cause(
                    Cause.of(
                        NamedCause.of(
                            DamageEntityEvent.GENERAL_ARMOR + ":" + type.getId(),
                            ((org.spongepowered.api.item.inventory.ItemStack) inventory[prop.slot])
                                .createSnapshot()),
                        NamedCause.of(
                            "ArmorProperty", prop), // We need this property to refer to the slot.
                        NamedCause.of("0xDEADBEEF", object))) // We need this object later on.
                .type(DamageModifierTypes.ARMOR)
                .build();
        modifiers.add(new Tuple<>(modifier, function));
        first = false;
      }
      if (modifiers.isEmpty()) {
        return Optional.empty();
      } else {
        return Optional.of(modifiers);
      }
    }
    return Optional.empty();
  }