53 lines
1.7 KiB
Go
53 lines
1.7 KiB
Go
|
|
package enchantment
|
||
|
|
|
||
|
|
import (
|
||
|
|
"github.com/df-mc/dragonfly/server/item"
|
||
|
|
"github.com/df-mc/dragonfly/server/world"
|
||
|
|
"math"
|
||
|
|
)
|
||
|
|
|
||
|
|
// AffectedDamageSource represents a world.DamageSource whose damage may be
|
||
|
|
// affected by an enchantment. A world.DamageSource does not need to implement
|
||
|
|
// AffectedDamageSource to let protection affect the damage. This happens
|
||
|
|
// depending on the (world.DamageSource).ReducedByResistance() method.
|
||
|
|
type AffectedDamageSource interface {
|
||
|
|
world.DamageSource
|
||
|
|
// AffectedByEnchantment specifies if a world.DamageSource is affected by
|
||
|
|
// the item.EnchantmentType passed.
|
||
|
|
AffectedByEnchantment(e item.EnchantmentType) bool
|
||
|
|
}
|
||
|
|
|
||
|
|
// DamageModifier is an item.EnchantmentType that can reduce damage through a
|
||
|
|
// modifier if an AffectedDamageSource returns true for it.
|
||
|
|
type DamageModifier interface {
|
||
|
|
Modifier() float64
|
||
|
|
}
|
||
|
|
|
||
|
|
// ProtectionFactor calculates the combined protection factor for a slice of
|
||
|
|
// item.Enchantment. The factor depends on the world.DamageSource passed and is
|
||
|
|
// in a range of [0, 0.8], where 0.8 means incoming damage would be reduced by
|
||
|
|
// 80%.
|
||
|
|
func ProtectionFactor(src world.DamageSource, enchantments []item.Enchantment) float64 {
|
||
|
|
f := 0.0
|
||
|
|
for _, e := range enchantments {
|
||
|
|
t := e.Type()
|
||
|
|
modifier, ok := t.(DamageModifier)
|
||
|
|
if !ok {
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
reduced := false
|
||
|
|
if _, ok := t.(protection); ok && src.ReducedByResistance() {
|
||
|
|
// Special case for protection, because it applies to all damage
|
||
|
|
// sources by default, except those not reduced by resistance.
|
||
|
|
reduced = true
|
||
|
|
} else if asrc, ok := src.(AffectedDamageSource); ok && asrc.AffectedByEnchantment(t) {
|
||
|
|
reduced = true
|
||
|
|
}
|
||
|
|
|
||
|
|
if reduced {
|
||
|
|
f += float64(e.Level()) * modifier.Modifier()
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return math.Min(f, 0.8)
|
||
|
|
}
|