use of org.spongepowered.api.event.cause.entity.damage.DamageFunction in project SpongeForge by SpongePowered.
the class StaticMixinForgeHelper method createArmorModifiers.
private static Optional<List<DamageFunction>> createArmorModifiers(List<ISpecialArmor.ArmorProperties> dmgVals, List<ItemStack> inventory, double damage) {
if (dmgVals.size() > 0) {
final List<DamageFunction> list = new ArrayList<>();
ISpecialArmor.ArmorProperties[] props = dmgVals.toArray(new ISpecialArmor.ArmorProperties[dmgVals.size()]);
sortProperties(props, damage);
boolean first = true;
int level = props[0].Priority;
double ratio = 0;
for (ISpecialArmor.ArmorProperties prop : props) {
EquipmentType type = DamageEventHandler.resolveEquipment(prop.Slot);
final DamageEventObject object = new DamageEventObject();
object.previousLevel = prop.Priority;
object.previousRatio = ratio;
if (first) {
object.previousDamage = damage;
object.augment = true;
}
DoubleUnaryOperator function = incomingDamage -> {
incomingDamage *= 25;
if (object.augment) {
damageToHandle = incomingDamage;
}
double functionDamage = damageToHandle;
object.previousDamage = functionDamage;
object.level = prop.Priority;
object.ratio = prop.AbsorbRatio;
if (object.previousLevel != prop.Priority) {
functionDamage -= (functionDamage * object.previousRatio);
damageToHandle = functionDamage;
object.ratio = 0;
object.level = prop.Priority;
}
object.ratio += prop.AbsorbRatio;
return -((functionDamage * prop.AbsorbRatio) / 25);
};
// We still need to "simulate" the original function so that the ratios are handled
if (level != prop.Priority) {
damage -= (damage * ratio);
ratio = 0;
level = prop.Priority;
}
ratio += prop.AbsorbRatio;
EventContextKey<ItemStackSnapshot> contextKey = ARMOR_KEYS.get("armor:" + type.getId());
if (contextKey == null) {
contextKey = new EventContextKey<ItemStackSnapshot>() {
@Override
public Class<ItemStackSnapshot> getAllowedType() {
return ItemStackSnapshot.class;
}
@Override
public String getId() {
return "armor:" + type.getId();
}
@Override
public String getName() {
return type.getName();
}
};
ARMOR_KEYS.put("armor: " + type.getId(), contextKey);
}
final ItemStack itemStack = inventory.get(prop.Slot);
DamageModifier modifier = DamageModifier.builder().cause(Cause.of(EventContext.builder().add(contextKey, ItemStackUtil.snapshotOf(itemStack)).add(ARMOR_PROPERTY, prop).add(DAMAGE_MODIFIER_OBJECT, object).build(), itemStack)).type(DamageModifierTypes.ARMOR).build();
list.add(DamageFunction.of(modifier, function));
first = false;
}
return Optional.of(list);
}
return Optional.empty();
}
use of org.spongepowered.api.event.cause.entity.damage.DamageFunction in project SpongeCommon by SpongePowered.
the class DamageEventHandler method provideCriticalAttackTuple.
public static DamageFunction provideCriticalAttackTuple(EntityPlayer player) {
// TODO: direct cause creation: bad bad bad
final DamageModifier modifier = DamageModifier.builder().cause(Cause.of(EventContext.empty(), player)).type(DamageModifierTypes.CRITICAL_HIT).build();
DoubleUnaryOperator function = (damage) -> damage * 1.5F;
return new DamageFunction(modifier, function);
}
use of org.spongepowered.api.event.cause.entity.damage.DamageFunction in project SpongeCommon by SpongePowered.
the class DamageEventHandler method createArmorModifiers.
public static Optional<List<DamageFunction>> createArmorModifiers(EntityLivingBase entityLivingBase, DamageSource damageSource, double damage) {
if (!damageSource.isUnblockable()) {
damage *= 25;
net.minecraft.item.ItemStack[] inventory = Iterables.toArray(entityLivingBase.getArmorInventoryList(), net.minecraft.item.ItemStack.class);
List<DamageFunction> 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.isEmpty()) {
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;
}
DoubleUnaryOperator 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;
// TODO: direct cause creation: bad bad bad
DamageModifier modifier = DamageModifier.builder().cause(Cause.of(EventContext.empty(), ((org.spongepowered.api.item.inventory.ItemStack) inventory[prop.slot]).createSnapshot(), // We need this property to refer to the slot.
prop, // We need this object later on.
object)).type(DamageModifierTypes.ARMOR).build();
modifiers.add(new DamageFunction(modifier, function));
first = false;
}
if (!modifiers.isEmpty()) {
return Optional.of(modifiers);
}
}
return Optional.empty();
}
use of org.spongepowered.api.event.cause.entity.damage.DamageFunction in project SpongeCommon by SpongePowered.
the class DamageEventHandler method createEnchantmentModifiers.
public static Optional<List<DamageFunction>> createEnchantmentModifiers(EntityLivingBase entityLivingBase, DamageSource damageSource) {
if (!damageSource.isDamageAbsolute()) {
Iterable<net.minecraft.item.ItemStack> inventory = entityLivingBase.getArmorInventoryList();
if (EnchantmentHelper.getEnchantmentModifierDamage(Lists.newArrayList(entityLivingBase.getArmorInventoryList()), damageSource) == 0) {
return Optional.empty();
}
List<DamageFunction> modifiers = new ArrayList<>();
boolean first = true;
int totalModifier = 0;
for (net.minecraft.item.ItemStack itemStack : inventory) {
if (itemStack.isEmpty()) {
continue;
}
final Multimap<Enchantment, Short> enchantments = LinkedHashMultimap.create();
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) {
enchantments.put(enchantment, level);
}
}
}
ItemStackSnapshot snapshot = ItemStackUtil.snapshotOf(itemStack);
for (Map.Entry<Enchantment, Collection<Short>> enchantment : enchantments.asMap().entrySet()) {
final DamageObject object = new DamageObject();
int modifierTemp = 0;
for (short level : enchantment.getValue()) {
modifierTemp += enchantment.getKey().calcModifierDamage(level, damageSource);
}
final int modifier = modifierTemp;
object.previousDamage = totalModifier;
if (object.previousDamage > 25) {
object.previousDamage = 25;
}
totalModifier += modifier;
object.augment = first;
object.ratio = modifier;
DoubleUnaryOperator 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 * j;
modifierDamage = magicModifier / 25.0F;
}
return -Math.max(actualDamage - modifierDamage, 0.0D);
};
if (first) {
first = false;
}
// TODO: direct cause creation: bad bad bad
DamageModifier enchantmentModifier = DamageModifier.builder().cause(Cause.of(EventContext.empty(), enchantment, snapshot, entityLivingBase)).type(DamageModifierTypes.ARMOR_ENCHANTMENT).build();
modifiers.add(new DamageFunction(enchantmentModifier, enchantmentFunction));
}
if (!modifiers.isEmpty()) {
return Optional.of(modifiers);
}
}
}
return Optional.empty();
}
use of org.spongepowered.api.event.cause.entity.damage.DamageFunction in project SpongeCommon by SpongePowered.
the class DamageEventHandler method provideCooldownAttackStrengthFunction.
public static DamageFunction provideCooldownAttackStrengthFunction(EntityPlayer player, float attackStrength) {
// TODO: direct cause creation: bad bad bad
final DamageModifier modifier = DamageModifier.builder().cause(Cause.of(EventContext.empty(), player)).type(DamageModifierTypes.ATTACK_COOLDOWN).build();
// The formula is as follows:
// Since damage needs to be "multiplied", this needs to basically add negative damage but re-add the "reduced" damage.
DoubleUnaryOperator function = (damage) -> -damage + (damage * (0.2F + attackStrength * attackStrength * 0.8F));
return new DamageFunction(modifier, function);
}
Aggregations