github.com/df-mc/dragonfly@v0.9.13/server/item/enchantment/damage.go (about)

     1  package enchantment
     2  
     3  import (
     4  	"github.com/df-mc/dragonfly/server/item"
     5  	"github.com/df-mc/dragonfly/server/world"
     6  	"math"
     7  )
     8  
     9  // AffectedDamageSource represents a world.DamageSource whose damage may be
    10  // affected by an enchantment. A world.DamageSource does not need to implement
    11  // AffectedDamageSource to let Protection affect the damage. This happens
    12  // depending on the (world.DamageSource).ReducedByResistance() method.
    13  type AffectedDamageSource interface {
    14  	world.DamageSource
    15  	// AffectedByEnchantment specifies if a world.DamageSource is affected by
    16  	// the item.EnchantmentType passed.
    17  	AffectedByEnchantment(e item.EnchantmentType) bool
    18  }
    19  
    20  // DamageModifier is an item.EnchantmentType that can reduce damage through a
    21  // modifier if an AffectedDamageSource returns true for it.
    22  type DamageModifier interface {
    23  	Modifier() float64
    24  }
    25  
    26  // ProtectionFactor calculates the combined protection factor for a slice of
    27  // item.Enchantment. The factor depends on the world.DamageSource passed and is
    28  // in a range of [0, 0.8], where 0.8 means incoming damage would be reduced by
    29  // 80%.
    30  func ProtectionFactor(src world.DamageSource, enchantments []item.Enchantment) float64 {
    31  	f := 0.0
    32  	for _, e := range enchantments {
    33  		t := e.Type()
    34  		modifier, ok := t.(DamageModifier)
    35  		if !ok {
    36  			continue
    37  		}
    38  		reduced := false
    39  		if _, ok := t.(Protection); ok && src.ReducedByResistance() {
    40  			// Special case for Protection, because it applies to all damage
    41  			// sources by default, except those not reduced by resistance.
    42  			reduced = true
    43  		} else if asrc, ok := src.(AffectedDamageSource); ok && asrc.AffectedByEnchantment(t) {
    44  			reduced = true
    45  		}
    46  
    47  		if reduced {
    48  			f += float64(e.Level()) * modifier.Modifier()
    49  		}
    50  	}
    51  	return math.Min(f, 0.8)
    52  }