public static Optional<Tuple<DamageModifier, Function<? super Double, Double>>> createResistanceModifier(EntityLivingBase entityLivingBase, DamageSource damageSource) { if (!damageSource.isDamageAbsolute() && entityLivingBase.isPotionActive(Potion.resistance) && damageSource != DamageSource.outOfWorld) { PotionEffect effect = ((PotionEffect) entityLivingBase.getActivePotionEffect(Potion.resistance)); return Optional.of( new Tuple<>( DamageModifier.builder() .cause(Cause.of(NamedCause.of(DamageEntityEvent.RESISTANCE, effect))) .type(DamageModifierTypes.DEFENSIVE_POTION_EFFECT) .build(), createResistanceFunction(effect.getAmplifier()))); } return Optional.empty(); }
public static Optional<Tuple<DamageModifier, Function<? super Double, Double>>> createHardHatModifier(EntityLivingBase entityLivingBase, DamageSource damageSource) { if ((damageSource instanceof FallingBlockDamageSource) && entityLivingBase.getEquipmentInSlot(4) != null) { DamageModifier modifier = DamageModifier.builder() .cause( Cause.of( NamedCause.of( DamageEntityEvent.HARD_HAT_ARMOR, ((ItemStack) entityLivingBase.getEquipmentInSlot(4)).createSnapshot()))) .type(DamageModifierTypes.HARD_HAT) .build(); return Optional.of(new Tuple<>(modifier, HARD_HAT_FUNCTION)); } return Optional.empty(); }
/** * Only used in Vanilla. The Forge version is much different. Basically, this accepts the various * "objects" needed to work for an armor piece to be "damaged". * * <p>This is also where we can likely throw a damage item event. * * @param entity * @param damageSource * @param modifier * @param damage */ public static void acceptArmorModifier( EntityLivingBase entity, DamageSource damageSource, DamageModifier modifier, double damage) { Optional<DamageObject> property = modifier.getCause().first(DamageObject.class); final net.minecraft.item.ItemStack[] inventory = entity instanceof EntityPlayer ? ((EntityPlayer) entity).inventory.armorInventory : entity.getInventory(); if (property.isPresent()) { damage = Math.abs(damage) * 25; net.minecraft.item.ItemStack stack = inventory[property.get().slot]; int itemDamage = (int) (damage / 25D < 1 ? 1 : damage / 25D); stack.damageItem(itemDamage, entity); if (stack.stackSize <= 0) { inventory[property.get().slot] = null; } } }
public static Optional<Tuple<DamageModifier, Function<? super Double, Double>>> createBlockingModifier(EntityLivingBase entityLivingBase, DamageSource damageSource) { if (!damageSource.isUnblockable() && (entityLivingBase instanceof EntityPlayer && ((EntityPlayer) entityLivingBase).isBlocking())) { DamageModifier modifier = DamageModifier.builder() .cause( Cause.of( NamedCause.of( DamageEntityEvent.BLOCKING, ((ItemStack) ((EntityPlayer) entityLivingBase).getCurrentEquippedItem()) .createSnapshot()))) .type(DamageModifierTypes.BLOCKING) .build(); return Optional.of(new Tuple<>(modifier, BLOCKING_FUNCTION)); } return Optional.empty(); }
public static Optional<Tuple<DamageModifier, Function<? super Double, Double>>> createAbsorptionModifier(EntityLivingBase entityLivingBase, DamageSource damageSource) { if (entityLivingBase.isPotionActive(Potion.absorption)) { Function<? super Double, Double> function = damage -> -(Math.max( damage - Math.max(damage - entityLivingBase.getAbsorptionAmount(), 0.0F), 0.0F)); DamageModifier modifier = DamageModifier.builder() .cause( Cause.of( NamedCause.of( DamageEntityEvent.ABSORPTION, entityLivingBase.getActivePotionEffect(Potion.absorption)), NamedCause.of(DamageEntityEvent.CREATOR, entityLivingBase))) .type(DamageModifierTypes.ABSORPTION) .build(); return Optional.of(new Tuple<>(modifier, function)); } return Optional.empty(); }
public static Optional<List<Tuple<DamageModifier, Function<? super Double, Double>>>> createEnchantmentModifiers(EntityLivingBase entityLivingBase, DamageSource damageSource) { net.minecraft.item.ItemStack[] inventory = entityLivingBase instanceof EntityPlayer ? ((EntityPlayer) entityLivingBase).inventory.armorInventory : entityLivingBase.getInventory(); if (EnchantmentHelper.getEnchantmentModifierDamage(inventory, damageSource) == 0) { return Optional.empty(); } List<Tuple<DamageModifier, Function<? super Double, Double>>> modifiers = new ArrayList<>(); boolean first = true; int totalModifier = 0; for (net.minecraft.item.ItemStack itemStack : inventory) { if (itemStack == null) { continue; } NBTTagList enchantmentList = itemStack.getEnchantmentTagList(); if (enchantmentList == null) { continue; } for (int i = 0; i < enchantmentList.tagCount(); ++i) { final short enchantmentId = enchantmentList.getCompoundTagAt(i).getShort(NbtDataUtil.ITEM_ENCHANTMENT_ID); final short level = enchantmentList.getCompoundTagAt(i).getShort(NbtDataUtil.ITEM_ENCHANTMENT_LEVEL); if (Enchantment.getEnchantmentById(enchantmentId) != null) { // Ok, we have an enchantment! final Enchantment enchantment = Enchantment.getEnchantmentById(enchantmentId); final int temp = enchantment.calcModifierDamage(level, damageSource); if (temp != 0) { ItemStackSnapshot snapshot = ((ItemStack) itemStack).createSnapshot(); // Now we can actually consider this as a modifier! final DamageObject object = new DamageObject(); int modifier = enchantment.calcModifierDamage(level, damageSource); object.previousDamage = totalModifier; if (object.previousDamage > 25) { object.previousDamage = 25; } totalModifier += modifier; object.augment = first; object.ratio = modifier; Function<? super Double, Double> enchantmentFunction = damageIn -> { if (object.augment) { enchantmentDamageTracked = damageIn; } if (damageIn <= 0) { return 0D; } double actualDamage = enchantmentDamageTracked; if (object.previousDamage > 25) { return 0D; } double modifierDamage = actualDamage; double magicModifier; if (modifier > 0 && modifier <= 20) { int j = 25 - modifier; magicModifier = modifierDamage * (float) j; modifierDamage = magicModifier / 25.0F; } return -Math.max(actualDamage - modifierDamage, 0.0D); }; if (first) { first = false; } DamageModifier enchantmentModifier = DamageModifier.builder() .cause( Cause.of( NamedCause.of("ArmorEnchantment", enchantment), NamedCause.of("ItemStack", snapshot), NamedCause.of(DamageEntityEvent.SOURCE, entityLivingBase))) .type(DamageModifierTypes.ARMOR_ENCHANTMENT) .build(); modifiers.add(new Tuple<>(enchantmentModifier, enchantmentFunction)); } } } } if (!modifiers.isEmpty()) { return Optional.of(modifiers); } else { return Optional.empty(); } }
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(); }