-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathALCombatRules.java
More file actions
136 lines (125 loc) · 6.5 KB
/
ALCombatRules.java
File metadata and controls
136 lines (125 loc) · 6.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package dev.shadowsoffire.attributeslib.api;
import dev.shadowsoffire.attributeslib.ALConfig;
import dev.shadowsoffire.attributeslib.AttributesLib;
import dev.shadowsoffire.attributeslib.api.ALObjects.Attributes;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.LivingEntity;
import java.math.BigDecimal;
/**
* Contains AL-specific combat calculations for armor and protection values.
*/
public class ALCombatRules {
/**
* Gets the amount of damage the user would take after applying protection points and protection bypass.<br>
* Protection bypass is based on {@linkplain Attributes#PROT_PIERCE Protection Pierce} and {@linkplain Attributes#PROT_SHRED Protection Shred}.
* <p>
* This is not invoked if the user does not have any protection points, and excess protection bypass has no effect.
*
* @param target The attack's target.
* @param src The DamageSource of the attack.
* @param amount The amount of damage the attack is currently dealing, after armor has been applied.
* @param protPoints The amount of protection points the target has against the incoming damage source.
* @return The modified damage value, after applying protection points, accounting for the attacker's bypass.
*/
public static float getDamageAfterProtection(LivingEntity target, DamageSource src, float amount, float protPoints) {
if (src.getEntity() instanceof LivingEntity attacker) {
float shred = (float) attacker.getAttributeValue(Attributes.PROT_SHRED);
if (shred > 0.001F) {
protPoints *= 1 - shred;
}
float pierce = (float) attacker.getAttributeValue(Attributes.PROT_PIERCE);
if (pierce > 0.001F) {
protPoints -= pierce;
}
}
if (protPoints <= 0) return amount;
return amount * getProtDamageReduction(protPoints);
}
/**
* Computes the damage reduction factor for the given amount of protection points.<br>
* Each protection point reduces damage by 2.5%, up to 85%.
* <p>
* In vanilla, each protection point reduces damage by 4%, up to 80%.
*
* @see #getDamageAfterProtection(LivingEntity, DamageSource, float, float)
*/
public static float getProtDamageReduction(float protPoints) {
if (ALConfig.getProtExpr().isPresent()) {
return ALConfig.getProtExpr().get().setVariable("protPoints", new BigDecimal(protPoints)).eval().floatValue();
}
return 1 - Math.min(0.025F * protPoints, 0.85F);
}
/**
* Gets the amount of damage the user would take after applying armor, toughness, and armor bypass.<br>
* Armor bypass is based on {@linkplain Attributes#ARMOR_PIERCE Armor Pierce} and {@linkplain Attributes#ARMOR_SHRED Armor Shred}.
* <p>
* Unlike protection bypass, additional armor bypass will cause unarmored targets to take additional damage.<br>
* Not invoked if the incoming damage source {linkplain DamageSource#isBypassArmor() bypasses armor}.
* <p>
* With the introduction of this attribute, armor toughness acts as a shield against armor bypass.<br>
* Each point of armor toughness reduces the effectiveness of all armor bypass by 2%, up to 60%.<br>
* That said, armor toughness no longer reduces damage, and only reduces armor bypass.
* <p>
*
* @param target The attack's target.
* @param src The DamageSource of the attack.
* @param amount The amount of damage the attack is currently dealing, after armor has been applied.
* @param armor The amount of armor points the target has.
* @param toughness The amount of armor toughness points the target has.
* @return The modified damage value, after applying armor, accounting for the attacker's bypass.
*/
public static float getDamageAfterArmor(LivingEntity target, DamageSource src, float amount, float armor, float toughness) {
//AttributesLib.LOGGER.info("getDamageAfterArmor was passed " + amount);
if (src.getEntity() instanceof LivingEntity attacker) {
float shred = (float) attacker.getAttributeValue(Attributes.ARMOR_SHRED);
float bypassResist = Math.min(toughness * 0.02F, 0.6F);
if (shred > 0.001F) {
shred *= 1 - bypassResist;
armor *= 1 - shred;
}
float pierce = (float) attacker.getAttributeValue(Attributes.ARMOR_PIERCE);
if (pierce > 0.001F) {
pierce *= 1 - bypassResist;
armor -= pierce;
}
}
if (armor <= 0) return amount;
return amount * getArmorDamageReduction(amount, armor);
}
/**
* Computes the A value used in the Y = A / (A + X) formula used by {@link #getArmorDamageReduction(float, float)}.<br>
* This value is a flat 10 for small damage values (< 20), and increases after that point.
* <p>
* This expression may be configured in the attributeslib.cfg file.
*
* @param damage The amount of incoming damage.
* @return The A value, for use in {@link #getArmorDamageReduction(float, float)}
*/
public static float getAValue(float damage) {
if (ALConfig.getAValueExpr().isPresent()) {
return ALConfig.getAValueExpr().get().setVariable("damage", new BigDecimal(damage)).eval().floatValue();
}
return damage < 20 ? 10 : 10 + (damage - 20) / 2;
}
/**
* Computes the damage reduction factor of the given armor level.<br>
* Armor reduces a percentage of incoming damage equal to <code>A / (A + armor)</code>, where A varies based on the damage.
* <p>
* Armor Toughness no longer impacts this calculation.
* <p>
* The vanilla calculation is <code>DR = clamp(armor - damage / (2 + toughness / 4), armor / 5, 20) / 25</code>
* <p>
* For comparisons, see https://i.imgur.com/2OHQhgp.png
*
* @see #getAValue(float)
* @see #getDamageAfterArmor(LivingEntity, DamageSource, float, float, float)
*/
public static float getArmorDamageReduction(float damage, float armor) {
// AttributesLib.LOGGER.info("getArmorDamageReduction was passed " + damage);
float a = getAValue(damage);
if (ALConfig.getArmorExpr().isPresent()) {
return ALConfig.getArmorExpr().get().setVariable("a", new BigDecimal(a)).setVariable("damage", new BigDecimal(damage)).setVariable("armor", new BigDecimal(armor)).eval().floatValue();
}
return a / (a + armor);
}
}