@@ -19,23 +19,24 @@ package com.lambda.util.combat
1919
2020import com.lambda.context.SafeContext
2121import com.lambda.core.annotations.InternalApi
22- import com.lambda.util.math.dist
22+ import com.lambda.util.math.distSq
2323import com.lambda.util.math.minus
2424import com.lambda.util.math.times
2525import com.lambda.util.world.WorldUtils.internalGetFastEntities
2626import com.lambda.util.world.fastEntitySearch
2727import com.lambda.util.world.toFastVec
28- import net.minecraft.enchantment.EnchantmentHelper
29- import net.minecraft.enchantment.ProtectionEnchantment
28+ import net.minecraft.entity.EquipmentSlot
3029import net.minecraft.entity.LivingEntity
3130import net.minecraft.entity.damage.DamageSource
3231import net.minecraft.entity.decoration.EndCrystalEntity
33- import net.minecraft.entity.effect.StatusEffects
34- import net.minecraft.registry.tag.DamageTypeTags
32+ import net.minecraft.entity.effect.StatusEffects.FIRE_RESISTANCE
33+ import net.minecraft.registry.tag.DamageTypeTags.DAMAGES_HELMET
34+ import net.minecraft.registry.tag.DamageTypeTags.IS_FIRE
35+ import net.minecraft.registry.tag.DamageTypeTags.IS_FREEZING
36+ import net.minecraft.registry.tag.EntityTypeTags.FREEZE_HURTS_EXTRA_TYPES
3537import net.minecraft.util.math.Vec3d
3638import net.minecraft.world.explosion.Explosion
37- import kotlin.math.max
38- import kotlin.math.min
39+ import net.minecraft.world.explosion.ExplosionImpl
3940
4041object CombatUtils {
4142 /* *
@@ -45,20 +46,22 @@ object CombatUtils {
4546 * @param damage The damage to apply
4647 */
4748 fun DamageSource.scale (entity : LivingEntity , damage : Double ): Double {
48- if (entity.blockedByShield( this )) return 0.0
49- val resistanceAmplifier = entity.getStatusEffect( StatusEffects . RESISTANCE )?.amplifier ? : - 1
49+ if (damage.isNaN() || damage.isInfinite())
50+ return Double . MAX_VALUE
5051
51- if (isIn(DamageTypeTags .BYPASSES_EFFECTS )) return damage
52+ if (entity.isAlwaysInvulnerableTo(this ) ||
53+ entity.isDead ||
54+ entity.blockedByShield(this ) ||
55+ isIn(IS_FIRE ) && entity.hasStatusEffect(FIRE_RESISTANCE )) return 0.0
5256
53- if (entity.hasStatusEffect( StatusEffects . RESISTANCE ) && ! isIn(DamageTypeTags . BYPASSES_RESISTANCE ))
54- return ( damage - max(damage * ( 25 - (resistanceAmplifier + 1 ) * 5 ) / 25.0 , 0.0 )).coerceAtLeast( 0.0 )
57+ if (isIn( IS_FREEZING ) && entity.type. isIn(FREEZE_HURTS_EXTRA_TYPES ))
58+ return damage * 5
5559
56- if (isIn(DamageTypeTags .BYPASSES_ENCHANTMENTS )) return damage
60+ if (isIn(DAMAGES_HELMET ) && ! entity.getEquippedStack(EquipmentSlot .HEAD ).isEmpty)
61+ return damage * 0.75
5762
58- val protectionAmount = EnchantmentHelper .getProtectionAmount(entity.armorItems, this )
59- if (protectionAmount > 0 ) return damage * (1.0 - min(protectionAmount, 20 ) / 25.0 )
60-
61- return damage
63+ return entity.applyArmorToDamage(this ,
64+ entity.modifyAppliedDamage(this , damage.toFloat())).toDouble()
6265 }
6366
6467 /* *
@@ -68,7 +71,7 @@ object CombatUtils {
6871 */
6972 fun SafeContext.hasDeadlyCrystal (minHealth : Double ) =
7073 fastEntitySearch<EndCrystalEntity >(12.0 )
71- .any { player.health - explosionDamage (it.pos, player, 6.0 ) <= minHealth}
74+ .any { player.health - crystalDamage (it.pos, player) <= minHealth }
7275
7376 /* *
7477 * Calculates the damage dealt by an explosion to a living entity
@@ -95,52 +98,12 @@ object CombatUtils {
9598 * @param power The [power of the explosion](https://minecraft.wiki/w/Explosion#Damage)
9699 */
97100 fun SafeContext.explosionDamage (position : Vec3d , entity : LivingEntity , power : Double ): Double {
98- val distance = entity dist position
101+ val distance = entity distSq position
99102
100- val impact = (1.0 - distance / (power * 2.0 )) * Explosion .getExposure(position, entity) * 0.4
101- val damage = world.difficulty.id * 3 * power * (impact * impact + impact) + 1
103+ val range = power * 2
104+ val impact = (1 - distance / range) * ExplosionImpl .calculateReceivedDamage(position, entity) * 0.4
105+ val damage = (impact * impact + impact) / 2.0 * 7.0 * range + 1
102106
103107 return Explosion .createDamageSource(world, null ).scale(entity, damage)
104108 }
105-
106- /* *
107- * Calculates the velocity of entities in the explosion
108- *
109- * @param explosion The explosion to calculate the velocity for
110- */
111- @OptIn(InternalApi ::class )
112- fun SafeContext.explosionVelocity (explosion : Explosion ): Map <LivingEntity , Vec3d > {
113- val ref = ArrayList <LivingEntity >()
114- internalGetFastEntities(explosion.position.toFastVec(), explosion.power * 2.0 , ref)
115- return ref.associateWith { entity -> explosionVelocity(entity, explosion) }
116- }
117-
118- /* *
119- * Calculates the velocity of a living entity affected by an explosion
120- *
121- * @param entity The entity to calculate the velocity for
122- * @param explosion The explosion to calculate the velocity for
123- */
124- fun explosionVelocity (entity : LivingEntity , explosion : Explosion ) =
125- explosionVelocity(entity, explosion.position, explosion.power.toDouble())
126-
127- /* *
128- * Calculates the velocity of a living entity affected by an explosion
129- *
130- * @param entity The entity to calculate the velocity for
131- * @param position The position of the explosion
132- * @param power The strength of the explosion
133- */
134- fun explosionVelocity (entity : LivingEntity , position : Vec3d , power : Double ): Vec3d {
135- val distance = entity.pos.distanceTo(position)
136-
137- val size = power * 2.0
138- val vel = ProtectionEnchantment .transformExplosionKnockback(
139- entity,
140- (1.0 - distance / size) * Explosion .getExposure(position, entity)
141- )
142-
143- val diff = entity.eyePos - position
144- return diff.normalize() * vel
145- }
146109}
0 commit comments