mirror of
https://github.com/Sollace/Unicopia.git
synced 2024-11-27 15:17:59 +01:00
Added some enchantments suggested by kerplamp
This commit is contained in:
parent
ec50aadda3
commit
c61801b507
27 changed files with 880 additions and 19 deletions
|
@ -12,6 +12,8 @@ public interface USounds {
|
||||||
SoundEvent BATPONY_EEEE = register("batpony_eeee");
|
SoundEvent BATPONY_EEEE = register("batpony_eeee");
|
||||||
SoundEvent CHANGELING_BUZZ = register("changeling_buzz");
|
SoundEvent CHANGELING_BUZZ = register("changeling_buzz");
|
||||||
|
|
||||||
|
SoundEvent AURA = register("aura");
|
||||||
|
|
||||||
SoundEvent RECORD_CRUSADE = register("record.crusade");
|
SoundEvent RECORD_CRUSADE = register("record.crusade");
|
||||||
SoundEvent RECORD_PET = register("record.pet");
|
SoundEvent RECORD_PET = register("record.pet");
|
||||||
SoundEvent RECORD_POPULAR = register("record.popular");
|
SoundEvent RECORD_POPULAR = register("record.popular");
|
||||||
|
|
|
@ -7,18 +7,23 @@ import net.minecraft.tag.Tag;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
public interface UTags {
|
public interface UTags {
|
||||||
Tag<Item> APPLES = register("apples");
|
Tag<Item> APPLES = item("apples");
|
||||||
Tag<Item> FESH_APPLES = register("fresh_apples");
|
Tag<Item> FESH_APPLES = item("fresh_apples");
|
||||||
|
|
||||||
Tag<Item> NON_TOXIC = register("non_toxic");
|
Tag<Item> NON_TOXIC = item("non_toxic");
|
||||||
Tag<Item> FAIRLY_TOXIC = register("fairly_toxic");
|
Tag<Item> FAIRLY_TOXIC = item("fairly_toxic");
|
||||||
Tag<Item> SEVERELY_TOXIC = register("severely_toxic");
|
Tag<Item> SEVERELY_TOXIC = item("severely_toxic");
|
||||||
|
|
||||||
Tag<Block> FRAGILE = TagRegistry.block(new Identifier("unicopia", "fragile"));
|
Tag<Block> FRAGILE = block("fragile");
|
||||||
|
Tag<Block> INTERESTING = block("interesting");
|
||||||
|
|
||||||
static Tag<Item> register(String name) {
|
static Tag<Item> item(String name) {
|
||||||
return TagRegistry.item(new Identifier("unicopia", name));
|
return TagRegistry.item(new Identifier("unicopia", name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Tag<Block> block(String name) {
|
||||||
|
return TagRegistry.block(new Identifier("unicopia", name));
|
||||||
|
}
|
||||||
|
|
||||||
static void bootstrap() { }
|
static void bootstrap() { }
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,12 +6,15 @@ import com.minelittlepony.unicopia.BlockDestructionManager;
|
||||||
import com.minelittlepony.unicopia.Race;
|
import com.minelittlepony.unicopia.Race;
|
||||||
import com.minelittlepony.unicopia.ability.data.Hit;
|
import com.minelittlepony.unicopia.ability.data.Hit;
|
||||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||||
|
import com.minelittlepony.unicopia.item.enchantment.UEnchantments;
|
||||||
import com.minelittlepony.unicopia.particle.ParticleUtils;
|
import com.minelittlepony.unicopia.particle.ParticleUtils;
|
||||||
import com.minelittlepony.unicopia.particle.UParticles;
|
import com.minelittlepony.unicopia.particle.UParticles;
|
||||||
import com.minelittlepony.unicopia.util.MagicalDamageSource;
|
import com.minelittlepony.unicopia.util.MagicalDamageSource;
|
||||||
import com.minelittlepony.unicopia.util.PosHelper;
|
import com.minelittlepony.unicopia.util.PosHelper;
|
||||||
import com.minelittlepony.unicopia.util.WorldEvent;
|
import com.minelittlepony.unicopia.util.WorldEvent;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.enchantment.EnchantmentHelper;
|
||||||
|
import net.minecraft.entity.LivingEntity;
|
||||||
import net.minecraft.entity.attribute.EntityAttributes;
|
import net.minecraft.entity.attribute.EntityAttributes;
|
||||||
import net.minecraft.entity.damage.DamageSource;
|
import net.minecraft.entity.damage.DamageSource;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
@ -80,19 +83,27 @@ public class EarthPonyStompAbility implements Ability<Hit> {
|
||||||
iplayer.waitForFall(() -> {
|
iplayer.waitForFall(() -> {
|
||||||
BlockPos center = PosHelper.findSolidGroundAt(player.getEntityWorld(), player.getBlockPos());
|
BlockPos center = PosHelper.findSolidGroundAt(player.getEntityWorld(), player.getBlockPos());
|
||||||
|
|
||||||
|
float heavyness = 1 + EnchantmentHelper.getEquipmentLevel(UEnchantments.HEAVY, player);
|
||||||
|
|
||||||
iplayer.getWorld().getOtherEntities(player, areaOfEffect.offset(iplayer.getOriginVector())).forEach(i -> {
|
iplayer.getWorld().getOtherEntities(player, areaOfEffect.offset(iplayer.getOriginVector())).forEach(i -> {
|
||||||
double dist = Math.sqrt(center.getSquaredDistance(i.getBlockPos()));
|
double dist = Math.sqrt(center.getSquaredDistance(i.getBlockPos()));
|
||||||
|
|
||||||
if (dist <= rad + 3) {
|
if (dist <= rad + 3) {
|
||||||
double force = dist / 5;
|
double inertia = dist / 5;
|
||||||
|
|
||||||
|
if (i instanceof LivingEntity) {
|
||||||
|
inertia *= 1 + EnchantmentHelper.getEquipmentLevel(UEnchantments.HEAVY, (LivingEntity)i);
|
||||||
|
}
|
||||||
|
inertia /= heavyness;
|
||||||
|
|
||||||
i.addVelocity(
|
i.addVelocity(
|
||||||
-(player.getX() - i.getX()) / force,
|
-(player.getX() - i.getX()) / inertia,
|
||||||
-(player.getY() - i.getY() - 2) / force + (dist < 1 ? dist : 0),
|
-(player.getY() - i.getY() - 2) / inertia + (dist < 1 ? dist : 0),
|
||||||
-(player.getZ() - i.getZ()) / force);
|
-(player.getZ() - i.getZ()) / inertia);
|
||||||
|
|
||||||
DamageSource damage = MagicalDamageSource.create("smash", player);
|
DamageSource damage = MagicalDamageSource.create("smash", player);
|
||||||
|
|
||||||
double amount = (4 * player.getAttributeInstance(EntityAttributes.GENERIC_ATTACK_DAMAGE).getValue()) / (float)dist;
|
double amount = (4 * player.getAttributeInstance(EntityAttributes.GENERIC_ATTACK_DAMAGE).getValue() + heavyness * 0.4) / (float)dist;
|
||||||
|
|
||||||
if (i instanceof PlayerEntity) {
|
if (i instanceof PlayerEntity) {
|
||||||
Race race = Pony.of((PlayerEntity)i).getSpecies();
|
Race race = Pony.of((PlayerEntity)i).getSpecies();
|
||||||
|
@ -109,10 +120,12 @@ public class EarthPonyStompAbility implements Ability<Hit> {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
BlockPos.iterate(center.add(-rad, -rad, -rad), center.add(rad, rad, rad)).forEach(i -> {
|
double radius = rad + heavyness * 0.3;
|
||||||
|
|
||||||
|
BlockPos.iterate(center.add(-radius, -radius, -radius), center.add(radius, radius, radius)).forEach(i -> {
|
||||||
double dist = Math.sqrt(i.getSquaredDistance(player.getX(), player.getY(), player.getZ(), true));
|
double dist = Math.sqrt(i.getSquaredDistance(player.getX(), player.getY(), player.getZ(), true));
|
||||||
|
|
||||||
if (dist <= rad) {
|
if (dist <= radius) {
|
||||||
spawnEffect(player.world, i, dist);
|
spawnEffect(player.world, i, dist);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -13,12 +13,14 @@ import com.minelittlepony.unicopia.ability.magic.Attached;
|
||||||
import com.minelittlepony.unicopia.ability.magic.Caster;
|
import com.minelittlepony.unicopia.ability.magic.Caster;
|
||||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||||
import com.minelittlepony.unicopia.item.FriendshipBraceletItem;
|
import com.minelittlepony.unicopia.item.FriendshipBraceletItem;
|
||||||
|
import com.minelittlepony.unicopia.item.enchantment.UEnchantments;
|
||||||
import com.minelittlepony.unicopia.particle.MagicParticleEffect;
|
import com.minelittlepony.unicopia.particle.MagicParticleEffect;
|
||||||
import com.minelittlepony.unicopia.particle.ParticleHandle;
|
import com.minelittlepony.unicopia.particle.ParticleHandle;
|
||||||
import com.minelittlepony.unicopia.particle.SphereParticleEffect;
|
import com.minelittlepony.unicopia.particle.SphereParticleEffect;
|
||||||
import com.minelittlepony.unicopia.projectile.ProjectileUtil;
|
import com.minelittlepony.unicopia.projectile.ProjectileUtil;
|
||||||
import com.minelittlepony.unicopia.util.shape.Sphere;
|
import com.minelittlepony.unicopia.util.shape.Sphere;
|
||||||
|
|
||||||
|
import net.minecraft.enchantment.EnchantmentHelper;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.EyeOfEnderEntity;
|
import net.minecraft.entity.EyeOfEnderEntity;
|
||||||
import net.minecraft.entity.FallingBlockEntity;
|
import net.minecraft.entity.FallingBlockEntity;
|
||||||
|
@ -182,6 +184,10 @@ public class ShieldSpell extends AbstractRangedAreaSpell implements Attached {
|
||||||
protected void applyForce(Vec3d pos, Entity target, double force, double distance) {
|
protected void applyForce(Vec3d pos, Entity target, double force, double distance) {
|
||||||
pos = target.getPos().subtract(pos).normalize().multiply(force);
|
pos = target.getPos().subtract(pos).normalize().multiply(force);
|
||||||
|
|
||||||
|
if (target instanceof LivingEntity) {
|
||||||
|
pos = pos.multiply(1 / (1 + EnchantmentHelper.getEquipmentLevel(UEnchantments.HEAVY, (LivingEntity)target)));
|
||||||
|
}
|
||||||
|
|
||||||
target.addVelocity(
|
target.addVelocity(
|
||||||
pos.x,
|
pos.x,
|
||||||
pos.y + (distance < 1 ? distance : 0),
|
pos.y + (distance < 1 ? distance : 0),
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
package com.minelittlepony.unicopia.client.sound;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.USounds;
|
||||||
|
import com.minelittlepony.unicopia.entity.Living;
|
||||||
|
import com.minelittlepony.unicopia.item.enchantment.SimpleEnchantment;
|
||||||
|
import com.minelittlepony.unicopia.item.enchantment.UEnchantments;
|
||||||
|
|
||||||
|
import net.minecraft.client.sound.MovingSoundInstance;
|
||||||
|
import net.minecraft.sound.SoundCategory;
|
||||||
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
|
||||||
|
public class MagicAuraSoundInstance extends MovingSoundInstance {
|
||||||
|
|
||||||
|
private final Living<?> living;
|
||||||
|
|
||||||
|
private float sourceVolume;
|
||||||
|
private float targetVolume;
|
||||||
|
private float interpolate;
|
||||||
|
|
||||||
|
private boolean fadingOut;
|
||||||
|
|
||||||
|
public MagicAuraSoundInstance(SoundCategory category, Living<?> living) {
|
||||||
|
super(USounds.AURA, category);
|
||||||
|
this.looping = true;
|
||||||
|
this.repeat = true;
|
||||||
|
this.living = living;
|
||||||
|
this.volume = 0;
|
||||||
|
setTargetVolume(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldAlwaysPlay() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick() {
|
||||||
|
Optional<SimpleEnchantment.Data> data = living.getEnchants().getOrEmpty(UEnchantments.GEM_LOCATION);
|
||||||
|
|
||||||
|
Vec3d pos = living.getOriginVector();
|
||||||
|
x = pos.x;
|
||||||
|
y = pos.y;
|
||||||
|
z = pos.z;
|
||||||
|
|
||||||
|
if (!living.getEntity().removed && data.isPresent()) {
|
||||||
|
float level = data.get().level;
|
||||||
|
if (level != targetVolume) {
|
||||||
|
setTargetVolume(level);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fadingOut = true;
|
||||||
|
setTargetVolume(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (interpolate < 1) {
|
||||||
|
interpolate = Math.min(interpolate + 0.4F, 1);
|
||||||
|
volume = MathHelper.lerp(interpolate, sourceVolume, targetVolume);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fadingOut && volume < 0.01F) {
|
||||||
|
setDone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setTargetVolume(float target) {
|
||||||
|
sourceVolume = volume;
|
||||||
|
targetVolume = target;
|
||||||
|
interpolate = 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,10 +6,17 @@ import com.minelittlepony.unicopia.ability.magic.Affine;
|
||||||
import com.minelittlepony.unicopia.ability.magic.Levelled;
|
import com.minelittlepony.unicopia.ability.magic.Levelled;
|
||||||
import com.minelittlepony.unicopia.ability.magic.Spell;
|
import com.minelittlepony.unicopia.ability.magic.Spell;
|
||||||
import com.minelittlepony.unicopia.ability.magic.spell.SpellRegistry;
|
import com.minelittlepony.unicopia.ability.magic.spell.SpellRegistry;
|
||||||
|
import com.minelittlepony.unicopia.entity.ai.WantItNeedItTargetGoal;
|
||||||
|
import com.minelittlepony.unicopia.entity.ai.WantItTakeItGoal;
|
||||||
|
|
||||||
import net.minecraft.entity.LivingEntity;
|
import net.minecraft.entity.LivingEntity;
|
||||||
|
import net.minecraft.entity.ai.goal.GoalSelector;
|
||||||
|
import net.minecraft.entity.attribute.DefaultAttributeContainer;
|
||||||
|
import net.minecraft.entity.attribute.EntityAttributes;
|
||||||
import net.minecraft.entity.data.DataTracker;
|
import net.minecraft.entity.data.DataTracker;
|
||||||
import net.minecraft.entity.data.TrackedData;
|
import net.minecraft.entity.data.TrackedData;
|
||||||
import net.minecraft.entity.data.TrackedDataHandlerRegistry;
|
import net.minecraft.entity.data.TrackedDataHandlerRegistry;
|
||||||
|
import net.minecraft.entity.mob.MobEntity;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
|
||||||
public class Creature extends Living<LivingEntity> {
|
public class Creature extends Living<LivingEntity> {
|
||||||
|
@ -26,6 +33,16 @@ public class Creature extends Living<LivingEntity> {
|
||||||
super(entity, EFFECT);
|
super(entity, EFFECT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void initAi(GoalSelector goals, GoalSelector targets) {
|
||||||
|
targets.add(1, new WantItNeedItTargetGoal((MobEntity)entity));
|
||||||
|
goals.add(1, new WantItTakeItGoal((MobEntity)entity));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void registerAttributes(DefaultAttributeContainer.Builder builder) {
|
||||||
|
builder.add(EntityAttributes.GENERIC_ATTACK_DAMAGE);
|
||||||
|
builder.add(EntityAttributes.GENERIC_ATTACK_KNOCKBACK);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Race getSpecies() {
|
public Race getSpecies() {
|
||||||
return Race.HUMAN;
|
return Race.HUMAN;
|
||||||
|
@ -55,6 +72,7 @@ public class Creature extends Living<LivingEntity> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void toNBT(CompoundTag compound) {
|
public void toNBT(CompoundTag compound) {
|
||||||
|
super.toNBT(compound);
|
||||||
Spell effect = getSpell(true);
|
Spell effect = getSpell(true);
|
||||||
|
|
||||||
if (effect != null) {
|
if (effect != null) {
|
||||||
|
@ -65,6 +83,7 @@ public class Creature extends Living<LivingEntity> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void fromNBT(CompoundTag compound) {
|
public void fromNBT(CompoundTag compound) {
|
||||||
|
super.fromNBT(compound);
|
||||||
if (compound.contains("effect")) {
|
if (compound.contains("effect")) {
|
||||||
setSpell(SpellRegistry.instance().createEffectFromNBT(compound.getCompound("effect")));
|
setSpell(SpellRegistry.instance().createEffectFromNBT(compound.getCompound("effect")));
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,97 @@
|
||||||
|
package com.minelittlepony.unicopia.entity;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.item.enchantment.SimpleEnchantment;
|
||||||
|
import com.minelittlepony.unicopia.item.enchantment.UEnchantments;
|
||||||
|
import com.minelittlepony.unicopia.util.NbtSerialisable;
|
||||||
|
|
||||||
|
import net.minecraft.enchantment.Enchantment;
|
||||||
|
import net.minecraft.enchantment.EnchantmentHelper;
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.nbt.ListTag;
|
||||||
|
import net.minecraft.nbt.StringTag;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
import net.minecraft.util.Tickable;
|
||||||
|
import net.minecraft.util.registry.Registry;
|
||||||
|
|
||||||
|
public class Enchantments implements NbtSerialisable, Tickable {
|
||||||
|
|
||||||
|
private final Living<?> entity;
|
||||||
|
|
||||||
|
private final Set<Enchantment> equippedEnchantments = new HashSet<>();
|
||||||
|
|
||||||
|
private final Map<Enchantment, SimpleEnchantment.Data> data = new HashMap<>();
|
||||||
|
|
||||||
|
Enchantments(Living<?> entity) {
|
||||||
|
this.entity = entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T extends SimpleEnchantment.Data> Optional<T> getOrEmpty(Enchantment enchantment) {
|
||||||
|
return Optional.ofNullable((T)data.get(enchantment));
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T extends SimpleEnchantment.Data> T computeIfAbsent(Enchantment enchantment, Supplier<T> factory) {
|
||||||
|
return (T)data.computeIfAbsent(enchantment, e -> factory.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T extends SimpleEnchantment.Data> T remove(Enchantment enchantment) {
|
||||||
|
return (T)data.remove(enchantment);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick() {
|
||||||
|
UEnchantments.REGISTRY.forEach(ench -> {
|
||||||
|
int level = EnchantmentHelper.getEquipmentLevel(ench, entity.getMaster());
|
||||||
|
|
||||||
|
boolean active = level > 0;
|
||||||
|
|
||||||
|
if (active != equippedEnchantments.contains(ench)) {
|
||||||
|
if (active) {
|
||||||
|
equippedEnchantments.add(ench);
|
||||||
|
ench.onEquipped(entity);
|
||||||
|
} else {
|
||||||
|
equippedEnchantments.remove(ench);
|
||||||
|
ench.onUnequipped(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (active) {
|
||||||
|
ench.onUserTick(entity, level);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void toNBT(CompoundTag compound) {
|
||||||
|
ListTag list = new ListTag();
|
||||||
|
equippedEnchantments.forEach(enchant -> {
|
||||||
|
Identifier id = Registry.ENCHANTMENT.getId(enchant);
|
||||||
|
if (id != null) {
|
||||||
|
list.add(StringTag.of(id.toString()));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
compound.put("enchants", list);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fromNBT(CompoundTag compound) {
|
||||||
|
equippedEnchantments.clear();
|
||||||
|
if (compound.contains("enchants")) {
|
||||||
|
compound.getList("enchants", 8).forEach(tag -> {
|
||||||
|
Registry.ENCHANTMENT.getOrEmpty(new Identifier(tag.asString())).ifPresent(equippedEnchantments::add);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -34,6 +34,8 @@ public abstract class Living<T extends LivingEntity> implements Equine<T>, Caste
|
||||||
|
|
||||||
private int invinsibilityTicks;
|
private int invinsibilityTicks;
|
||||||
|
|
||||||
|
private final Enchantments enchants = new Enchantments(this);
|
||||||
|
|
||||||
protected Living(T entity, TrackedData<CompoundTag> effect) {
|
protected Living(T entity, TrackedData<CompoundTag> effect) {
|
||||||
this.entity = entity;
|
this.entity = entity;
|
||||||
this.effectDelegate = new EffectSync(this, effect);
|
this.effectDelegate = new EffectSync(this, effect);
|
||||||
|
@ -58,6 +60,10 @@ public abstract class Living<T extends LivingEntity> implements Equine<T>, Caste
|
||||||
return effectDelegate;
|
return effectDelegate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Enchantments getEnchants() {
|
||||||
|
return enchants;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setMaster(T owner) {
|
public void setMaster(T owner) {
|
||||||
}
|
}
|
||||||
|
@ -93,6 +99,8 @@ public abstract class Living<T extends LivingEntity> implements Equine<T>, Caste
|
||||||
if (getPhysics().isGravityNegative() && entity.getY() > entity.world.getHeight() + 64) {
|
if (getPhysics().isGravityNegative() && entity.getY() > entity.world.getHeight() + 64) {
|
||||||
entity.damage(DamageSource.OUT_OF_WORLD, 4.0F);
|
entity.damage(DamageSource.OUT_OF_WORLD, 4.0F);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enchants.tick();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -152,4 +160,14 @@ public abstract class Living<T extends LivingEntity> implements Equine<T>, Caste
|
||||||
spell.getDisguise().onImpact(this, distance, damageMultiplier);
|
spell.getDisguise().onImpact(this, distance, damageMultiplier);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void toNBT(CompoundTag compound) {
|
||||||
|
enchants.toNBT(compound);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fromNBT(CompoundTag compound) {
|
||||||
|
enchants.fromNBT(compound);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
package com.minelittlepony.unicopia.entity.ai;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.minelittlepony.unicopia.item.enchantment.UEnchantments;
|
||||||
|
|
||||||
|
import net.minecraft.enchantment.EnchantmentHelper;
|
||||||
|
import net.minecraft.entity.LivingEntity;
|
||||||
|
import net.minecraft.entity.ai.brain.MemoryModuleType;
|
||||||
|
import net.minecraft.entity.ai.brain.sensor.Sensor;
|
||||||
|
import net.minecraft.server.world.ServerWorld;
|
||||||
|
|
||||||
|
public class WantItNeedItSensor extends Sensor<LivingEntity> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<MemoryModuleType<?>> getOutputMemoryModules() {
|
||||||
|
return ImmutableSet.of(MemoryModuleType.ATTACK_TARGET, MemoryModuleType.VISIBLE_MOBS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void sense(ServerWorld world, LivingEntity entity) {
|
||||||
|
entity.getBrain().getOptionalMemory(MemoryModuleType.VISIBLE_MOBS).ifPresent(targets -> {
|
||||||
|
|
||||||
|
Optional<LivingEntity> target = targets.stream()
|
||||||
|
.filter(e -> (EnchantmentHelper.getEquipmentLevel(UEnchantments.DESIRED, e) * 10) >= entity.distanceTo(e))
|
||||||
|
.findFirst();
|
||||||
|
|
||||||
|
entity.getBrain().remember(MemoryModuleType.ATTACK_TARGET, target);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
package com.minelittlepony.unicopia.entity.ai;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.item.enchantment.UEnchantments;
|
||||||
|
import net.minecraft.enchantment.EnchantmentHelper;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.LivingEntity;
|
||||||
|
import net.minecraft.entity.ai.TargetPredicate;
|
||||||
|
import net.minecraft.entity.ai.goal.Goal;
|
||||||
|
import net.minecraft.entity.mob.MobEntity;
|
||||||
|
|
||||||
|
public class WantItNeedItTargetGoal extends Goal {
|
||||||
|
|
||||||
|
private final TargetPredicate predicate;
|
||||||
|
|
||||||
|
private final MobEntity mob;
|
||||||
|
|
||||||
|
private int interval;
|
||||||
|
|
||||||
|
public WantItNeedItTargetGoal(MobEntity mob) {
|
||||||
|
this.predicate = new TargetPredicate()
|
||||||
|
.setBaseMaxDistance(64)
|
||||||
|
.setPredicate(WantItNeedItTargetGoal::canTarget);
|
||||||
|
this.mob = mob;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canStart() {
|
||||||
|
if (interval-- <= 0) {
|
||||||
|
interval = 20;
|
||||||
|
Optional<LivingEntity> target = mob.world.getOtherEntities(mob, mob.getBoundingBox().expand(16, 16, 16),
|
||||||
|
e -> e instanceof LivingEntity && predicate.test(mob, (LivingEntity)e))
|
||||||
|
.stream()
|
||||||
|
.map(e -> (LivingEntity)e)
|
||||||
|
.sorted(Comparator.comparing((Entity e) -> mob.distanceTo(e)))
|
||||||
|
.findFirst();
|
||||||
|
|
||||||
|
if (target.isPresent()) {
|
||||||
|
mob.setTarget(target.get());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldContinue() {
|
||||||
|
LivingEntity target = mob.getTarget();
|
||||||
|
return target != null && mob.isTarget(target, TargetPredicate.DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean canTarget(LivingEntity e) {
|
||||||
|
return EnchantmentHelper.getEquipmentLevel(UEnchantments.DESIRED, e) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,140 @@
|
||||||
|
package com.minelittlepony.unicopia.entity.ai;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.EnumSet;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.AwaitTickQueue;
|
||||||
|
import com.minelittlepony.unicopia.item.enchantment.UEnchantments;
|
||||||
|
import com.minelittlepony.unicopia.particle.FollowingParticleEffect;
|
||||||
|
import com.minelittlepony.unicopia.particle.ParticleUtils;
|
||||||
|
import com.minelittlepony.unicopia.particle.UParticles;
|
||||||
|
import com.minelittlepony.unicopia.util.VecHelper;
|
||||||
|
|
||||||
|
import net.minecraft.enchantment.EnchantmentHelper;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.EquipmentSlot;
|
||||||
|
import net.minecraft.entity.ItemEntity;
|
||||||
|
import net.minecraft.entity.LivingEntity;
|
||||||
|
import net.minecraft.entity.ai.goal.Goal;
|
||||||
|
import net.minecraft.entity.mob.MobEntity;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
|
||||||
|
public class WantItTakeItGoal extends Goal {
|
||||||
|
|
||||||
|
private final MobEntity mob;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private LivingEntity target;
|
||||||
|
@Nullable
|
||||||
|
private ItemEntity item;
|
||||||
|
|
||||||
|
private int cooldown;
|
||||||
|
|
||||||
|
public WantItTakeItGoal(MobEntity mob) {
|
||||||
|
this.mob = mob;
|
||||||
|
this.setControls(EnumSet.of(Goal.Control.MOVE, Goal.Control.LOOK));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canStart() {
|
||||||
|
LivingEntity target = mob.getTarget();
|
||||||
|
if (target == null || !WantItNeedItTargetGoal.canTarget(target)) {
|
||||||
|
|
||||||
|
Optional<ItemEntity> item = VecHelper.findInRange(mob, mob.world, mob.getPos(), 16,
|
||||||
|
e -> !e.removed && e instanceof ItemEntity && EnchantmentHelper.getLevel(UEnchantments.DESIRED, ((ItemEntity)e).getStack()) > 0)
|
||||||
|
.stream()
|
||||||
|
.map(e -> (ItemEntity)e)
|
||||||
|
.sorted(Comparator.comparing((Entity e) -> mob.distanceTo(e)))
|
||||||
|
.findFirst();
|
||||||
|
|
||||||
|
if (item.isPresent()) {
|
||||||
|
this.item = item.get();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.target = target;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldContinue() {
|
||||||
|
return (target == null || (
|
||||||
|
target.isAlive()
|
||||||
|
&& WantItNeedItTargetGoal.canTarget(target)
|
||||||
|
&& mob.squaredDistanceTo(target) <= 225))
|
||||||
|
&& (item == null || item.isAlive())
|
||||||
|
&& (!mob.getNavigation().isIdle() || canStart());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stop() {
|
||||||
|
target = null;
|
||||||
|
item = null;
|
||||||
|
mob.getNavigation().stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick() {
|
||||||
|
if (target == null && (item == null || item.removed)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity targetEntity = target == null ? item : target;
|
||||||
|
|
||||||
|
mob.getLookControl().lookAt(targetEntity, 30, 30);
|
||||||
|
|
||||||
|
double reach = mob.getWidth() * 2 * mob.getWidth() * 2;
|
||||||
|
double distance = mob.squaredDistanceTo(targetEntity.getX(), targetEntity.getY(), targetEntity.getZ());
|
||||||
|
|
||||||
|
double speed = 0.8D;
|
||||||
|
|
||||||
|
if (distance > reach && distance < 16) {
|
||||||
|
speed = 1.33;
|
||||||
|
} else if (distance < 225) {
|
||||||
|
speed = 0.6;
|
||||||
|
}
|
||||||
|
speed *= 2;
|
||||||
|
|
||||||
|
ParticleUtils.spawnParticles(new FollowingParticleEffect(UParticles.HEALTH_DRAIN, mob, 0.2F), mob, 1);
|
||||||
|
|
||||||
|
mob.getNavigation().startMovingTo(targetEntity, speed);
|
||||||
|
|
||||||
|
cooldown = Math.max(this.cooldown - 1, 0);
|
||||||
|
if (distance <= reach) {
|
||||||
|
if (target != null) {
|
||||||
|
if (cooldown <= 0) {
|
||||||
|
cooldown = 20;
|
||||||
|
mob.tryAttack(target);
|
||||||
|
|
||||||
|
if (mob.world.random.nextInt(20) == 0) {
|
||||||
|
for (EquipmentSlot slot : EquipmentSlot.values()) {
|
||||||
|
ItemStack stack = target.getEquippedStack(slot);
|
||||||
|
if (EnchantmentHelper.getLevel(UEnchantments.DESIRED, stack) > 0) {
|
||||||
|
target.equipStack(slot, ItemStack.EMPTY);
|
||||||
|
AwaitTickQueue.scheduleTask(mob.world, w -> {
|
||||||
|
mob.tryEquip(stack);
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ItemStack stack = item.getStack();
|
||||||
|
AwaitTickQueue.scheduleTask(mob.world, w -> {
|
||||||
|
if (!item.removed) {
|
||||||
|
mob.tryEquip(stack);
|
||||||
|
mob.method_29499(item);
|
||||||
|
mob.sendPickup(item, stack.getCount());
|
||||||
|
item.remove();
|
||||||
|
}
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,11 +6,13 @@ import com.minelittlepony.unicopia.USounds;
|
||||||
import com.minelittlepony.unicopia.ability.magic.Spell;
|
import com.minelittlepony.unicopia.ability.magic.Spell;
|
||||||
import com.minelittlepony.unicopia.entity.EntityPhysics;
|
import com.minelittlepony.unicopia.entity.EntityPhysics;
|
||||||
import com.minelittlepony.unicopia.entity.player.MagicReserves.Bar;
|
import com.minelittlepony.unicopia.entity.player.MagicReserves.Bar;
|
||||||
|
import com.minelittlepony.unicopia.item.enchantment.UEnchantments;
|
||||||
import com.minelittlepony.unicopia.util.NbtSerialisable;
|
import com.minelittlepony.unicopia.util.NbtSerialisable;
|
||||||
import com.minelittlepony.unicopia.util.MutableVector;
|
import com.minelittlepony.unicopia.util.MutableVector;
|
||||||
|
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.enchantment.EnchantmentHelper;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.EntityPose;
|
import net.minecraft.entity.EntityPose;
|
||||||
import net.minecraft.entity.attribute.EntityAttributeInstance;
|
import net.minecraft.entity.attribute.EntityAttributeInstance;
|
||||||
|
@ -196,6 +198,12 @@ public class PlayerPhysics extends EntityPhysics<Pony> implements Tickable, Moti
|
||||||
|
|
||||||
lastPos = new Vec3d(entity.getX(), 0, entity.getZ());
|
lastPos = new Vec3d(entity.getX(), 0, entity.getZ());
|
||||||
|
|
||||||
|
if (!entity.isOnGround()) {
|
||||||
|
float heavyness = 1 - EnchantmentHelper.getEquipmentLevel(UEnchantments.HEAVY, entity) * 0.015F;
|
||||||
|
velocity.x *= heavyness;
|
||||||
|
velocity.z *= heavyness;
|
||||||
|
}
|
||||||
|
|
||||||
entity.setVelocity(velocity.toImmutable());
|
entity.setVelocity(velocity.toImmutable());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,12 +253,17 @@ public class PlayerPhysics extends EntityPhysics<Pony> implements Tickable, Moti
|
||||||
thrustScale *= 0.1889F;
|
thrustScale *= 0.1889F;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float heavyness = EnchantmentHelper.getEquipmentLevel(UEnchantments.HEAVY, player) / 6F;
|
||||||
float thrustStrength = 0.135F * thrustScale;
|
float thrustStrength = 0.135F * thrustScale;
|
||||||
|
if (heavyness > 0) {
|
||||||
|
thrustStrength /= heavyness;
|
||||||
|
}
|
||||||
|
|
||||||
Vec3d direction = player.getRotationVec(1).normalize().multiply(thrustStrength);
|
Vec3d direction = player.getRotationVec(1).normalize().multiply(thrustStrength);
|
||||||
|
|
||||||
velocity.x += direction.x;
|
velocity.x += direction.x;
|
||||||
velocity.z += direction.z;
|
velocity.z += direction.z;
|
||||||
velocity.y += (direction.y * 2.45 + Math.abs(direction.y) * 10) * getGravitySignum();
|
velocity.y += (direction.y * 2.45 + Math.abs(direction.y) * 10) * getGravitySignum() - heavyness / 5F;
|
||||||
|
|
||||||
if (player.isSneaking()) {
|
if (player.isSneaking()) {
|
||||||
if (!isGravityNegative()) {
|
if (!isGravityNegative()) {
|
||||||
|
@ -264,7 +277,7 @@ public class PlayerPhysics extends EntityPhysics<Pony> implements Tickable, Moti
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void applyTurbulance(Entity player, MutableVector velocity) {
|
protected void applyTurbulance(PlayerEntity player, MutableVector velocity) {
|
||||||
float glance = 360 * player.world.random.nextFloat();
|
float glance = 360 * player.world.random.nextFloat();
|
||||||
float forward = 0.015F * player.world.random.nextFloat() * player.world.getRainGradient(1);
|
float forward = 0.015F * player.world.random.nextFloat() * player.world.getRainGradient(1);
|
||||||
|
|
||||||
|
@ -287,6 +300,7 @@ public class PlayerPhysics extends EntityPhysics<Pony> implements Tickable, Moti
|
||||||
}
|
}
|
||||||
|
|
||||||
forward = Math.min(forward, 7);
|
forward = Math.min(forward, 7);
|
||||||
|
forward /= 1 + (EnchantmentHelper.getEquipmentLevel(UEnchantments.HEAVY, player) * 0.8F);
|
||||||
|
|
||||||
velocity.x += - forward * MathHelper.sin((player.yaw + glance) * 0.017453292F);
|
velocity.x += - forward * MathHelper.sin((player.yaw + glance) * 0.017453292F);
|
||||||
velocity.z += forward * MathHelper.cos((player.yaw + glance) * 0.017453292F);
|
velocity.z += forward * MathHelper.cos((player.yaw + glance) * 0.017453292F);
|
||||||
|
|
|
@ -276,10 +276,10 @@ public class Pony extends Living<PlayerEntity> implements Transmittable, Copieab
|
||||||
ticksHanging = 0;
|
ticksHanging = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
super.tick();
|
|
||||||
|
|
||||||
tickers.forEach(Tickable::tick);
|
tickers.forEach(Tickable::tick);
|
||||||
|
|
||||||
|
super.tick();
|
||||||
|
|
||||||
if (dirty) {
|
if (dirty) {
|
||||||
sendCapabilities(true);
|
sendCapabilities(true);
|
||||||
}
|
}
|
||||||
|
@ -376,6 +376,7 @@ public class Pony extends Living<PlayerEntity> implements Transmittable, Copieab
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void toNBT(CompoundTag compound) {
|
public void toNBT(CompoundTag compound) {
|
||||||
|
super.toNBT(compound);
|
||||||
compound.putString("playerSpecies", getSpecies().name());
|
compound.putString("playerSpecies", getSpecies().name());
|
||||||
|
|
||||||
compound.putFloat("magicExhaustion", magicExhaustion);
|
compound.putFloat("magicExhaustion", magicExhaustion);
|
||||||
|
@ -392,6 +393,7 @@ public class Pony extends Living<PlayerEntity> implements Transmittable, Copieab
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void fromNBT(CompoundTag compound) {
|
public void fromNBT(CompoundTag compound) {
|
||||||
|
super.fromNBT(compound);
|
||||||
speciesPersisted = true;
|
speciesPersisted = true;
|
||||||
setSpecies(Race.fromName(compound.getString("playerSpecies")));
|
setSpecies(Race.fromName(compound.getString("playerSpecies")));
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.USounds;
|
import com.minelittlepony.unicopia.USounds;
|
||||||
|
import com.minelittlepony.unicopia.item.enchantment.UEnchantments;
|
||||||
import com.minelittlepony.unicopia.item.toxin.ToxicHolder;
|
import com.minelittlepony.unicopia.item.toxin.ToxicHolder;
|
||||||
import com.minelittlepony.unicopia.item.toxin.Toxics;
|
import com.minelittlepony.unicopia.item.toxin.Toxics;
|
||||||
import com.minelittlepony.unicopia.item.toxin.UFoodComponents;
|
import com.minelittlepony.unicopia.item.toxin.UFoodComponents;
|
||||||
|
@ -72,6 +73,7 @@ public interface UItems {
|
||||||
|
|
||||||
static void bootstrap() {
|
static void bootstrap() {
|
||||||
Toxics.bootstrap();
|
Toxics.bootstrap();
|
||||||
|
UEnchantments.bootstrap();
|
||||||
URecipes.bootstrap();
|
URecipes.bootstrap();
|
||||||
|
|
||||||
FabricItemGroupBuilder.create(new Identifier("unicopia", "items")).appendItems(list -> {
|
FabricItemGroupBuilder.create(new Identifier("unicopia", "items")).appendItems(list -> {
|
||||||
|
@ -81,7 +83,7 @@ public interface UItems {
|
||||||
.map(Item::getDefaultStack)
|
.map(Item::getDefaultStack)
|
||||||
.collect(Collectors.toList())
|
.collect(Collectors.toList())
|
||||||
);
|
);
|
||||||
}).icon(ZAP_APPLE::getDefaultStack).build();
|
}).icon(EMPTY_JAR::getDefaultStack).build();
|
||||||
|
|
||||||
FabricItemGroupBuilder.create(new Identifier("unicopia", "horsefeed")).appendItems(list -> {
|
FabricItemGroupBuilder.create(new Identifier("unicopia", "horsefeed")).appendItems(list -> {
|
||||||
list.addAll(Registry.ITEM.stream()
|
list.addAll(Registry.ITEM.stream()
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
package com.minelittlepony.unicopia.item.enchantment;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.IntFunction;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.entity.Living;
|
||||||
|
|
||||||
|
import net.minecraft.enchantment.EnchantmentTarget;
|
||||||
|
import net.minecraft.entity.EquipmentSlot;
|
||||||
|
import net.minecraft.entity.LivingEntity;
|
||||||
|
import net.minecraft.entity.attribute.EntityAttribute;
|
||||||
|
import net.minecraft.entity.attribute.EntityAttributeInstance;
|
||||||
|
import net.minecraft.entity.attribute.EntityAttributeModifier;
|
||||||
|
|
||||||
|
public class AttributedEnchantment extends SimpleEnchantment {
|
||||||
|
|
||||||
|
private final Map<EntityAttribute, IntFunction<EntityAttributeModifier>> modifiers = new HashMap<>();
|
||||||
|
|
||||||
|
protected AttributedEnchantment(Rarity rarity, EnchantmentTarget target, boolean cursed, int maxLevel, EquipmentSlot... slots) {
|
||||||
|
super(rarity, target, cursed, maxLevel, slots);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected AttributedEnchantment(Rarity rarity, boolean cursed, int maxLevel, EquipmentSlot... slots) {
|
||||||
|
super(rarity, cursed, maxLevel, slots);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AttributedEnchantment addModifier(EntityAttribute attribute, IntFunction<EntityAttributeModifier> modifierSupplier) {
|
||||||
|
modifiers.put(attribute, modifierSupplier);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUserTick(Living<?> user, int level) {
|
||||||
|
if (shouldChangeModifiers(user, level)) {
|
||||||
|
LivingEntity entity = user.getMaster();
|
||||||
|
modifiers.forEach((attr, modifierSupplier) -> {
|
||||||
|
EntityAttributeInstance instance = entity.getAttributeInstance(attr);
|
||||||
|
|
||||||
|
EntityAttributeModifier modifier = modifierSupplier.apply(level);
|
||||||
|
|
||||||
|
instance.removeModifier(modifier.getId());
|
||||||
|
instance.addPersistentModifier(modifier);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUnequipped(Living<?> user) {
|
||||||
|
LivingEntity entity = user.getMaster();
|
||||||
|
modifiers.forEach((attr, modifierSupplier) -> {
|
||||||
|
EntityAttributeInstance instance = entity.getAttributeInstance(attr);
|
||||||
|
|
||||||
|
instance.tryRemoveModifier(modifierSupplier.apply(1).getId());
|
||||||
|
});
|
||||||
|
user.getEnchants().remove(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean shouldChangeModifiers(Living<?> user, int level) {
|
||||||
|
return user.getEnchants().computeIfAbsent(this, Data::new).update(level);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
package com.minelittlepony.unicopia.item.enchantment;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.UTags;
|
||||||
|
import com.minelittlepony.unicopia.client.sound.MagicAuraSoundInstance;
|
||||||
|
import com.minelittlepony.unicopia.entity.Living;
|
||||||
|
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.enchantment.EnchantmentTarget;
|
||||||
|
import net.minecraft.entity.EquipmentSlot;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
|
||||||
|
public class GemFindingEnchantment extends SimpleEnchantment {
|
||||||
|
|
||||||
|
protected GemFindingEnchantment() {
|
||||||
|
super(Rarity.RARE, EnchantmentTarget.DIGGER, false, 3, EquipmentSlot.MAINHAND, EquipmentSlot.OFFHAND);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUserTick(Living<?> user, int level) {
|
||||||
|
int radius = 2 + (level * 2);
|
||||||
|
|
||||||
|
BlockPos origin = user.getOrigin();
|
||||||
|
|
||||||
|
float volume = BlockPos.findClosest(origin, radius, radius, pos -> user.getWorld().getBlockState(pos).isIn(UTags.INTERESTING))
|
||||||
|
.map(p -> user.getOriginVector().squaredDistanceTo(p.getX(), p.getY(), p.getZ()))
|
||||||
|
.map(find -> (1 - (MathHelper.sqrt(find) / radius)))
|
||||||
|
.orElse(-1F);
|
||||||
|
|
||||||
|
volume = Math.max(volume, 0.04F);
|
||||||
|
|
||||||
|
user.getEnchants().computeIfAbsent(this, Data::new).level = volume * (1.3F + level * 0.3F);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEquipped(Living<?> user) {
|
||||||
|
if (user.isClient()) {
|
||||||
|
MinecraftClient.getInstance().getSoundManager().play(new MagicAuraSoundInstance(user.getEntity().getSoundCategory(), user));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUnequipped(Living<?> user) {
|
||||||
|
user.getEnchants().remove(this).level = 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
package com.minelittlepony.unicopia.item.enchantment;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.entity.Living;
|
||||||
|
|
||||||
|
import net.minecraft.enchantment.Enchantment;
|
||||||
|
import net.minecraft.enchantment.EnchantmentTarget;
|
||||||
|
import net.minecraft.entity.EquipmentSlot;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
|
||||||
|
public class SimpleEnchantment extends Enchantment {
|
||||||
|
|
||||||
|
private final boolean cursed;
|
||||||
|
|
||||||
|
private final boolean allItems;
|
||||||
|
|
||||||
|
private final int maxLevel;
|
||||||
|
|
||||||
|
protected SimpleEnchantment(Rarity rarity, EnchantmentTarget target, boolean cursed, int maxLevel, EquipmentSlot... slots) {
|
||||||
|
super(rarity, target, slots);
|
||||||
|
this.cursed = cursed;
|
||||||
|
this.allItems = false;
|
||||||
|
this.maxLevel = maxLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected SimpleEnchantment(Rarity rarity, boolean cursed, int maxLevel, EquipmentSlot... slots) {
|
||||||
|
super(rarity, EnchantmentTarget.VANISHABLE, slots); // vanishable includes breakable. It's the one that accepts the widest variety of items
|
||||||
|
this.cursed = cursed;
|
||||||
|
this.allItems = true;
|
||||||
|
this.maxLevel = maxLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onUserTick(Living<?> user, int level) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onEquipped(Living<?> user) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onUnequipped(Living<?> user) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAcceptableItem(ItemStack itemStack) {
|
||||||
|
return allItems || super.isAcceptableItem(itemStack);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaxLevel() {
|
||||||
|
return maxLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCursed() {
|
||||||
|
return cursed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Data {
|
||||||
|
public float level;
|
||||||
|
|
||||||
|
public boolean update(int level) {
|
||||||
|
if (level == this.level) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this.level = level;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
package com.minelittlepony.unicopia.item.enchantment;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.entity.Living;
|
||||||
|
import com.minelittlepony.unicopia.entity.player.MagicReserves.Bar;
|
||||||
|
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||||
|
|
||||||
|
import net.minecraft.entity.EquipmentSlot;
|
||||||
|
|
||||||
|
public class StressfulEnchantment extends SimpleEnchantment {
|
||||||
|
|
||||||
|
protected StressfulEnchantment() {
|
||||||
|
super(Rarity.COMMON, true, 3, EquipmentSlot.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUserTick(Living<?> user, int level) {
|
||||||
|
if (user instanceof Pony) {
|
||||||
|
Bar bar = ((Pony)user).getMagicalReserves().getEnergy();
|
||||||
|
float targetPercent = (level / (float)getMaxLevel()) * 0.5F;
|
||||||
|
if (bar.getPercentFill() < targetPercent) {
|
||||||
|
bar.add(20);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
package com.minelittlepony.unicopia.item.enchantment;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import net.minecraft.enchantment.Enchantment;
|
||||||
|
import net.minecraft.enchantment.Enchantment.Rarity;
|
||||||
|
import net.minecraft.entity.EquipmentSlot;
|
||||||
|
import net.minecraft.entity.attribute.EntityAttributeModifier;
|
||||||
|
import net.minecraft.entity.attribute.EntityAttributes;
|
||||||
|
import net.minecraft.entity.attribute.EntityAttributeModifier.Operation;
|
||||||
|
import net.minecraft.enchantment.EnchantmentTarget;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
import net.minecraft.util.registry.Registry;
|
||||||
|
|
||||||
|
public interface UEnchantments {
|
||||||
|
|
||||||
|
List<SimpleEnchantment> REGISTRY = new ArrayList<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes a sound when there are interesting blocks in your area.
|
||||||
|
*/
|
||||||
|
Enchantment GEM_LOCATION = register("gem_location", new GemFindingEnchantment());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Protects against wall collisions and earth pony attacks!
|
||||||
|
*
|
||||||
|
* TODO:
|
||||||
|
*/
|
||||||
|
Enchantment PADDED = register("padded", new SimpleEnchantment(Rarity.COMMON, EnchantmentTarget.ARMOR, false, 3, EquipmentSlot.HEAD, EquipmentSlot.CHEST, EquipmentSlot.LEGS, EquipmentSlot.FEET));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Heavy players move more slowly but are less likely to be flung around wildly.
|
||||||
|
*
|
||||||
|
* TODO:
|
||||||
|
*/
|
||||||
|
Enchantment HEAVY = register("heavy", new AttributedEnchantment(Rarity.COMMON, EnchantmentTarget.ARMOR_FEET, false, 4, EquipmentSlot.FEET))
|
||||||
|
.addModifier(EntityAttributes.GENERIC_MOVEMENT_SPEED, level -> {
|
||||||
|
// 1 -> 0.9
|
||||||
|
// 2 -> 0.8
|
||||||
|
// 3 -> 0.7
|
||||||
|
return new EntityAttributeModifier(UUID.fromString("a3d5a94f-4c40-48f6-a343-558502a13e10"), "Heavyness", (1 - level/(float)10) - 1, Operation.MULTIPLY_TOTAL);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* It's dangerous to go alone, take this!
|
||||||
|
*
|
||||||
|
* Weapons will become stronger the more allies you have around.
|
||||||
|
*
|
||||||
|
* TODO:
|
||||||
|
*/
|
||||||
|
Enchantment COLLABORATOR = register("collaborator", new SimpleEnchantment(Rarity.COMMON, EnchantmentTarget.WEAPON, false, 1, EquipmentSlot.MAINHAND));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* I want it, I neeeed it!
|
||||||
|
*
|
||||||
|
* Mobs really want your candy. You'd better give it to them.
|
||||||
|
*/
|
||||||
|
Enchantment DESIRED = register("desired", new WantItNeedItEnchantment());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hahaha geddit?
|
||||||
|
*
|
||||||
|
* Random things happen.
|
||||||
|
*
|
||||||
|
* TODO:
|
||||||
|
*/
|
||||||
|
Enchantment POISON_JOKE = register("poison_joke", new SimpleEnchantment(Rarity.COMMON, true, 3, EquipmentSlot.values()));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Who doesn't like a good freakout?
|
||||||
|
*/
|
||||||
|
Enchantment STRESS = register("stress", new StressfulEnchantment());
|
||||||
|
|
||||||
|
static void bootstrap() { }
|
||||||
|
|
||||||
|
static <T extends SimpleEnchantment> T register(String name, T enchantment) {
|
||||||
|
REGISTRY.add(enchantment);
|
||||||
|
return Registry.register(Registry.ENCHANTMENT, new Identifier("unicopia", name), enchantment);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package com.minelittlepony.unicopia.item.enchantment;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.entity.Creature;
|
||||||
|
import com.minelittlepony.unicopia.entity.Living;
|
||||||
|
import com.minelittlepony.unicopia.particle.FollowingParticleEffect;
|
||||||
|
import com.minelittlepony.unicopia.particle.ParticleUtils;
|
||||||
|
import com.minelittlepony.unicopia.particle.UParticles;
|
||||||
|
|
||||||
|
import net.minecraft.entity.EquipmentSlot;
|
||||||
|
|
||||||
|
public class WantItNeedItEnchantment extends SimpleEnchantment {
|
||||||
|
|
||||||
|
protected WantItNeedItEnchantment() {
|
||||||
|
super(Rarity.VERY_RARE, true, 1, EquipmentSlot.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUserTick(Living<?> user, int level) {
|
||||||
|
if (user instanceof Creature && user.getWorld().random.nextInt(10) == 0) {
|
||||||
|
ParticleUtils.spawnParticles(new FollowingParticleEffect(UParticles.HEALTH_DRAIN, user.getEntity(), 0.2F), user.getEntity(), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,6 +22,7 @@ import com.minelittlepony.unicopia.entity.ItemWielder;
|
||||||
|
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.LivingEntity;
|
import net.minecraft.entity.LivingEntity;
|
||||||
|
import net.minecraft.entity.attribute.DefaultAttributeContainer;
|
||||||
import net.minecraft.entity.damage.DamageSource;
|
import net.minecraft.entity.damage.DamageSource;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
@ -58,6 +59,11 @@ abstract class MixinLivingEntity extends Entity implements PonyContainer<Equine<
|
||||||
return caster;
|
return caster;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Inject(method = "createLivingAttributes()Lnet/minecraft/entity/attribute/DefaultAttributeContainer$Builder;", at = @At("RETURN"))
|
||||||
|
private static void onCreateAttributes(CallbackInfoReturnable<DefaultAttributeContainer.Builder> info) {
|
||||||
|
Creature.registerAttributes(info.getReturnValue());
|
||||||
|
}
|
||||||
|
|
||||||
@Inject(method = "isClimbing()Z", at = @At("HEAD"), cancellable = true)
|
@Inject(method = "isClimbing()Z", at = @At("HEAD"), cancellable = true)
|
||||||
public void onIsClimbing(CallbackInfoReturnable<Boolean> info) {
|
public void onIsClimbing(CallbackInfoReturnable<Boolean> info) {
|
||||||
if (get() instanceof Pony && horizontalCollision) {
|
if (get() instanceof Pony && horizontalCollision) {
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
package com.minelittlepony.unicopia.mixin;
|
||||||
|
|
||||||
|
import org.spongepowered.asm.mixin.Final;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
import com.minelittlepony.unicopia.entity.Creature;
|
||||||
|
import com.minelittlepony.unicopia.entity.PonyContainer;
|
||||||
|
import com.minelittlepony.unicopia.entity.Equine;
|
||||||
|
import net.minecraft.entity.LivingEntity;
|
||||||
|
import net.minecraft.entity.ai.goal.GoalSelector;
|
||||||
|
import net.minecraft.entity.mob.MobEntity;
|
||||||
|
|
||||||
|
@Mixin(MobEntity.class)
|
||||||
|
abstract class MixinMobEntity extends LivingEntity implements PonyContainer<Equine<?>> {
|
||||||
|
private MixinMobEntity() { super(null, null); }
|
||||||
|
|
||||||
|
@Shadow
|
||||||
|
protected @Final GoalSelector goalSelector;
|
||||||
|
@Shadow
|
||||||
|
protected @Final GoalSelector targetSelector;
|
||||||
|
|
||||||
|
@Inject(method = "<init>()V", at = @At("RETURN"), remap = false)
|
||||||
|
private void init(CallbackInfo info) {
|
||||||
|
((Creature)get()).initAi(goalSelector, targetSelector);
|
||||||
|
}
|
||||||
|
}
|
|
@ -163,6 +163,14 @@
|
||||||
|
|
||||||
"key.unicopia.hud_page_dn": "Hud Previous Page",
|
"key.unicopia.hud_page_dn": "Hud Previous Page",
|
||||||
"key.unicopia.hud_page_up": "Hud Next Page",
|
"key.unicopia.hud_page_up": "Hud Next Page",
|
||||||
|
|
||||||
|
"enchantment.unicopia.gem_location": "Gem Locator",
|
||||||
|
"enchantment.unicopia.padded": "Padded",
|
||||||
|
"enchantment.unicopia.heavy": "Heavy",
|
||||||
|
"enchantment.unicopia.collaborator": "Collaborator",
|
||||||
|
"enchantment.unicopia.desired": "Want It Need It",
|
||||||
|
"enchantment.unicopia.poison_joke": "Poisoned Joke",
|
||||||
|
"enchantment.unicopia.stress": "Stressful",
|
||||||
|
|
||||||
"commands.race.success.self": "Your race has been updated",
|
"commands.race.success.self": "Your race has been updated",
|
||||||
"commands.race.success.otherself": "%1$s changed race to %2$s",
|
"commands.race.success.otherself": "%1$s changed race to %2$s",
|
||||||
|
|
|
@ -9,6 +9,12 @@
|
||||||
"unicopia:wing/wing3"
|
"unicopia:wing/wing3"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"aura": {
|
||||||
|
"category": "player",
|
||||||
|
"sounds": [
|
||||||
|
"unicopia:aura/aura0"
|
||||||
|
]
|
||||||
|
},
|
||||||
"batpony_eeee": {
|
"batpony_eeee": {
|
||||||
"category": "player",
|
"category": "player",
|
||||||
"subtitle": "unicopia.subtitle.batpony_eeee",
|
"subtitle": "unicopia.subtitle.batpony_eeee",
|
||||||
|
|
BIN
src/main/resources/assets/unicopia/sounds/aura/aura0.ogg
Normal file
BIN
src/main/resources/assets/unicopia/sounds/aura/aura0.ogg
Normal file
Binary file not shown.
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"replace": false,
|
||||||
|
"values": [
|
||||||
|
"minecraft:coal_ore",
|
||||||
|
"minecraft:iron_ore",
|
||||||
|
"minecraft:gold_ore",
|
||||||
|
"minecraft:emerald_ore",
|
||||||
|
"minecraft:lapis_ore",
|
||||||
|
"minecraft:diamond_ore",
|
||||||
|
"minecraft:nether_gold_ore",
|
||||||
|
"minecraft:nether_quartz_ore",
|
||||||
|
"minecraft:sea_lantern",
|
||||||
|
"minecraft:ender_chest",
|
||||||
|
"minecraft:end_portal_frame",
|
||||||
|
"minecraft:jukebox",
|
||||||
|
"minecraft:spawner"
|
||||||
|
]
|
||||||
|
}
|
|
@ -13,6 +13,7 @@
|
||||||
"MixinItems",
|
"MixinItems",
|
||||||
"MixinLivingEntity",
|
"MixinLivingEntity",
|
||||||
"MixinMilkBucketItem",
|
"MixinMilkBucketItem",
|
||||||
|
"MixinMobEntity",
|
||||||
"MixinPersistentProjectileEntity",
|
"MixinPersistentProjectileEntity",
|
||||||
"MixinPlayerEntity",
|
"MixinPlayerEntity",
|
||||||
"MixinProjectileEntity",
|
"MixinProjectileEntity",
|
||||||
|
|
Loading…
Reference in a new issue