mirror of
https://github.com/Sollace/Unicopia.git
synced 2025-02-14 17:14:22 +01:00
Add broken alicorn amulet, and further tweaks the sombra
This commit is contained in:
parent
30c91050db
commit
0320976d47
20 changed files with 284 additions and 71 deletions
|
@ -83,7 +83,13 @@ public class SombraEntityModel extends EntityModel<SombraEntity> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void animateModel(SombraEntity entity, float limbAngle, float limbDistance, float tickDelta) {
|
public void animateModel(SombraEntity entity, float limbAngle, float limbDistance, float tickDelta) {
|
||||||
float jawsOpenAmount = entity.getBiteAmount(tickDelta); //(1 - Math.max(0, MathHelper.sin(ageInTicks * 0.1F)));
|
float jawsOpenAmount = entity.getBiteAmount(tickDelta);
|
||||||
|
float scale = entity.getScaleFactor(tickDelta) * 1.7F;
|
||||||
|
|
||||||
|
part.pivotY = scale * -20;
|
||||||
|
part.xScale = scale;
|
||||||
|
part.yScale = scale;
|
||||||
|
part.zScale = scale;
|
||||||
|
|
||||||
lowerJaw.resetTransform();
|
lowerJaw.resetTransform();
|
||||||
lowerJaw.pivotY -= jawsOpenAmount * 3;
|
lowerJaw.pivotY -= jawsOpenAmount * 3;
|
||||||
|
@ -96,14 +102,8 @@ public class SombraEntityModel extends EntityModel<SombraEntity> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setAngles(SombraEntity entity, float limbAngle, float limbDistance, float animationProgress, float netHeadYaw, float headPitch) {
|
public void setAngles(SombraEntity entity, float limbAngle, float limbDistance, float animationProgress, float netHeadYaw, float headPitch) {
|
||||||
float scale = 1.6F;
|
|
||||||
|
|
||||||
part.xScale = scale;
|
|
||||||
part.yScale = scale;
|
|
||||||
part.zScale = scale;
|
|
||||||
|
|
||||||
part.yaw = -MathHelper.HALF_PI;
|
part.yaw = -MathHelper.HALF_PI;
|
||||||
part.pivotY = MathHelper.sin(animationProgress * 0.05F) - 12;
|
part.pivotY += MathHelper.sin(animationProgress * 0.05F);
|
||||||
part.pivotZ = MathHelper.cos(animationProgress * 0.045F);
|
part.pivotZ = MathHelper.cos(animationProgress * 0.045F);
|
||||||
|
|
||||||
head.pitch = headPitch * MathHelper.RADIANS_PER_DEGREE;
|
head.pitch = headPitch * MathHelper.RADIANS_PER_DEGREE;
|
||||||
|
|
|
@ -9,6 +9,7 @@ import net.minecraft.entity.LivingEntity;
|
||||||
public interface AmuletSelectors {
|
public interface AmuletSelectors {
|
||||||
Predicate<LivingEntity> ALICORN_AMULET = UItems.ALICORN_AMULET::isApplicable;
|
Predicate<LivingEntity> ALICORN_AMULET = UItems.ALICORN_AMULET::isApplicable;
|
||||||
Predicate<LivingEntity> PEGASUS_AMULET = UItems.PEGASUS_AMULET::isApplicable;
|
Predicate<LivingEntity> PEGASUS_AMULET = UItems.PEGASUS_AMULET::isApplicable;
|
||||||
|
Predicate<LivingEntity> UNICORN_AMULET = UItems.UNICORN_AMULET::isApplicable;
|
||||||
|
|
||||||
Predicate<LivingEntity> ALICORN_AMULET_AFTER_1_DAYS = ALICORN_AMULET.and(ItemTracker.wearing(UItems.ALICORN_AMULET, ItemTracker.after(ItemTracker.DAYS)));
|
Predicate<LivingEntity> ALICORN_AMULET_AFTER_1_DAYS = ALICORN_AMULET.and(ItemTracker.wearing(UItems.ALICORN_AMULET, ItemTracker.after(ItemTracker.DAYS)));
|
||||||
Predicate<LivingEntity> ALICORN_AMULET_AFTER_2_DAYS = ALICORN_AMULET.and(ItemTracker.wearing(UItems.ALICORN_AMULET, ItemTracker.after(2 * ItemTracker.DAYS)));
|
Predicate<LivingEntity> ALICORN_AMULET_AFTER_2_DAYS = ALICORN_AMULET.and(ItemTracker.wearing(UItems.ALICORN_AMULET, ItemTracker.after(2 * ItemTracker.DAYS)));
|
||||||
|
|
|
@ -120,6 +120,11 @@ public class Creature extends Living<LivingEntity> implements WeaklyOwned.Mutabl
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initAi(GoalSelector goals, GoalSelector targets) {
|
public void initAi(GoalSelector goals, GoalSelector targets) {
|
||||||
|
|
||||||
|
if (entity instanceof SombraEntity) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.goals = Optional.of(goals);
|
this.goals = Optional.of(goals);
|
||||||
this.targets = Optional.of(targets);
|
this.targets = Optional.of(targets);
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,7 @@ public class CrystalShardsEntity extends Entity {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Set<Direction> getOccupiedFaces(World world, BlockPos pos) {
|
public static Set<Direction> getOccupiedFaces(World world, BlockPos pos) {
|
||||||
return world.getEntitiesByClass(CrystalShardsEntity.class, new Box(pos).expand(1), EntityPredicates.VALID_ENTITY)
|
return world.getEntitiesByClass(CrystalShardsEntity.class, new Box(pos).expand(4), EntityPredicates.VALID_ENTITY)
|
||||||
.stream()
|
.stream()
|
||||||
.map(e -> e.getAttachmentFace())
|
.map(e -> e.getAttachmentFace())
|
||||||
.distinct()
|
.distinct()
|
||||||
|
|
|
@ -10,19 +10,17 @@ import com.minelittlepony.unicopia.USounds;
|
||||||
import com.minelittlepony.unicopia.entity.ai.ArenaAttackGoal;
|
import com.minelittlepony.unicopia.entity.ai.ArenaAttackGoal;
|
||||||
import com.minelittlepony.unicopia.item.AmuletItem;
|
import com.minelittlepony.unicopia.item.AmuletItem;
|
||||||
import com.minelittlepony.unicopia.item.UItems;
|
import com.minelittlepony.unicopia.item.UItems;
|
||||||
import com.minelittlepony.unicopia.particle.ParticleHandle;
|
|
||||||
import com.minelittlepony.unicopia.particle.ParticleHandle.Attachment;
|
|
||||||
import com.minelittlepony.unicopia.particle.ParticleSource;
|
import com.minelittlepony.unicopia.particle.ParticleSource;
|
||||||
import com.minelittlepony.unicopia.particle.ParticleUtils;
|
import com.minelittlepony.unicopia.particle.ParticleUtils;
|
||||||
import com.minelittlepony.unicopia.particle.SphereParticleEffect;
|
|
||||||
import com.minelittlepony.unicopia.particle.UParticles;
|
|
||||||
import com.minelittlepony.unicopia.util.VecHelper;
|
import com.minelittlepony.unicopia.util.VecHelper;
|
||||||
import com.minelittlepony.unicopia.util.shape.Sphere;
|
import com.minelittlepony.unicopia.util.shape.Sphere;
|
||||||
|
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.EntityType;
|
import net.minecraft.entity.EntityType;
|
||||||
|
import net.minecraft.entity.ExperienceOrbEntity;
|
||||||
import net.minecraft.entity.LivingEntity;
|
import net.minecraft.entity.LivingEntity;
|
||||||
|
import net.minecraft.entity.MovementType;
|
||||||
import net.minecraft.entity.ai.goal.ActiveTargetGoal;
|
import net.minecraft.entity.ai.goal.ActiveTargetGoal;
|
||||||
import net.minecraft.entity.ai.goal.FlyGoal;
|
import net.minecraft.entity.ai.goal.FlyGoal;
|
||||||
import net.minecraft.entity.ai.goal.LongDoorInteractGoal;
|
import net.minecraft.entity.ai.goal.LongDoorInteractGoal;
|
||||||
|
@ -40,6 +38,7 @@ import net.minecraft.entity.attribute.DefaultAttributeContainer;
|
||||||
import net.minecraft.entity.attribute.EntityAttributes;
|
import net.minecraft.entity.attribute.EntityAttributes;
|
||||||
import net.minecraft.entity.boss.BossBar;
|
import net.minecraft.entity.boss.BossBar;
|
||||||
import net.minecraft.entity.boss.ServerBossBar;
|
import net.minecraft.entity.boss.ServerBossBar;
|
||||||
|
import net.minecraft.entity.boss.BossBar.Style;
|
||||||
import net.minecraft.entity.damage.DamageSource;
|
import net.minecraft.entity.damage.DamageSource;
|
||||||
import net.minecraft.entity.data.DataTracker;
|
import net.minecraft.entity.data.DataTracker;
|
||||||
import net.minecraft.entity.data.TrackedData;
|
import net.minecraft.entity.data.TrackedData;
|
||||||
|
@ -67,7 +66,9 @@ import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.Direction;
|
import net.minecraft.util.math.Direction;
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
import net.minecraft.world.GameRules;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraft.world.WorldEvents;
|
||||||
import net.minecraft.world.event.GameEvent;
|
import net.minecraft.world.event.GameEvent;
|
||||||
|
|
||||||
public class SombraEntity extends HostileEntity implements ArenaCombatant, ParticleSource<SombraEntity> {
|
public class SombraEntity extends HostileEntity implements ArenaCombatant, ParticleSource<SombraEntity> {
|
||||||
|
@ -76,18 +77,17 @@ public class SombraEntity extends HostileEntity implements ArenaCombatant, Parti
|
||||||
static final Predicate<Entity> EFFECT_TARGET_PREDICATE = EntityPredicates.VALID_LIVING_ENTITY.and(EntityPredicates.EXCEPT_CREATIVE_OR_SPECTATOR);
|
static final Predicate<Entity> EFFECT_TARGET_PREDICATE = EntityPredicates.VALID_LIVING_ENTITY.and(EntityPredicates.EXCEPT_CREATIVE_OR_SPECTATOR);
|
||||||
|
|
||||||
private static final TrackedData<Optional<BlockPos>> HOME_POS = DataTracker.registerData(SombraEntity.class, TrackedDataHandlerRegistry.OPTIONAL_BLOCK_POS);
|
private static final TrackedData<Optional<BlockPos>> HOME_POS = DataTracker.registerData(SombraEntity.class, TrackedDataHandlerRegistry.OPTIONAL_BLOCK_POS);
|
||||||
|
private static final TrackedData<Float> TARGET_SIZE = DataTracker.registerData(SombraEntity.class, TrackedDataHandlerRegistry.FLOAT);
|
||||||
|
|
||||||
private final ServerBossBar bossBar = (ServerBossBar)new ServerBossBar(getDisplayName(), BossBar.Color.PURPLE, BossBar.Style.PROGRESS)
|
private final ServerBossBar bossBar;
|
||||||
.setDarkenSky(true)
|
|
||||||
.setThickenFog(true);
|
|
||||||
|
|
||||||
private final ParticleHandle shroud = new ParticleHandle();
|
|
||||||
|
|
||||||
final EntityReference<StormCloudEntity> stormCloud = new EntityReference<>();
|
final EntityReference<StormCloudEntity> stormCloud = new EntityReference<>();
|
||||||
|
|
||||||
private int prevBiteTime;
|
private int prevBiteTime;
|
||||||
private int biteTime;
|
private int biteTime;
|
||||||
|
|
||||||
|
private float prevSize;
|
||||||
|
private float currentSize;
|
||||||
|
|
||||||
public static void startEncounter(World world, BlockPos pos) {
|
public static void startEncounter(World world, BlockPos pos) {
|
||||||
StormCloudEntity cloud = UEntities.STORM_CLOUD.create(world);
|
StormCloudEntity cloud = UEntities.STORM_CLOUD.create(world);
|
||||||
cloud.setPosition(pos.up(10).toCenterPos());
|
cloud.setPosition(pos.up(10).toCenterPos());
|
||||||
|
@ -97,8 +97,18 @@ public class SombraEntity extends HostileEntity implements ArenaCombatant, Parti
|
||||||
}
|
}
|
||||||
|
|
||||||
public SombraEntity(EntityType<SombraEntity> type, World world) {
|
public SombraEntity(EntityType<SombraEntity> type, World world) {
|
||||||
|
this(type, world, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SombraEntity(EntityType<SombraEntity> type, World world, @Nullable ServerBossBar bossBar) {
|
||||||
super(type, world);
|
super(type, world);
|
||||||
bossBar.setStyle(BossBar.Style.NOTCHED_10);
|
this.bossBar = bossBar == null ? createBossBar(getDisplayName()) : bossBar;
|
||||||
|
this.bossBar.setName(getDisplayName());
|
||||||
|
this.bossBar.setStyle(Style.NOTCHED_10);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ServerBossBar createBossBar(Text name) {
|
||||||
|
return new SombraBossBar(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DefaultAttributeContainer.Builder createMobAttributes() {
|
public static DefaultAttributeContainer.Builder createMobAttributes() {
|
||||||
|
@ -137,6 +147,7 @@ public class SombraEntity extends HostileEntity implements ArenaCombatant, Parti
|
||||||
protected void initDataTracker() {
|
protected void initDataTracker() {
|
||||||
super.initDataTracker();
|
super.initDataTracker();
|
||||||
dataTracker.startTracking(HOME_POS, Optional.empty());
|
dataTracker.startTracking(HOME_POS, Optional.empty());
|
||||||
|
dataTracker.startTracking(TARGET_SIZE, 1F);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -182,7 +193,21 @@ public class SombraEntity extends HostileEntity implements ArenaCombatant, Parti
|
||||||
|
|
||||||
public float getBiteAmount(float tickDelta) {
|
public float getBiteAmount(float tickDelta) {
|
||||||
float progress = (MathHelper.lerp(tickDelta, prevBiteTime, biteTime) / (float)MAX_BITE_TIME);
|
float progress = (MathHelper.lerp(tickDelta, prevBiteTime, biteTime) / (float)MAX_BITE_TIME);
|
||||||
return 1 - Math.abs(MathHelper.sin(progress * MathHelper.PI));
|
return 1 - Math.abs(MathHelper.sin(progress * MathHelper.PI * 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getScaleFactor() {
|
||||||
|
return Math.max(1, dataTracker.get(TARGET_SIZE));
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getScaleFactor(float tickDelta) {
|
||||||
|
return MathHelper.lerp(tickDelta, prevSize, currentSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setScaleFactor(float targetSize) {
|
||||||
|
dataTracker.set(TARGET_SIZE, targetSize);
|
||||||
|
calculateDimensions();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -191,8 +216,8 @@ public class SombraEntity extends HostileEntity implements ArenaCombatant, Parti
|
||||||
Optional<BlockPos> homePos = getHomePos();
|
Optional<BlockPos> homePos = getHomePos();
|
||||||
|
|
||||||
if (homePos.isEmpty() && !isRemoved()) {
|
if (homePos.isEmpty() && !isRemoved()) {
|
||||||
remove(RemovalReason.DISCARDED);
|
setHomePos(getBlockPos());
|
||||||
return;
|
homePos = getHomePos();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getBlockPos().getSquaredDistance(homePos.get()) > MathHelper.square(getAreaRadius())) {
|
if (getBlockPos().getSquaredDistance(homePos.get()) > MathHelper.square(getAreaRadius())) {
|
||||||
|
@ -205,19 +230,34 @@ public class SombraEntity extends HostileEntity implements ArenaCombatant, Parti
|
||||||
biteTime--;
|
biteTime--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float targetSize = getScaleFactor();
|
||||||
|
boolean sizeChanging = prevSize != currentSize;
|
||||||
|
prevSize = currentSize;
|
||||||
|
tickGrowth(targetSize, sizeChanging);
|
||||||
|
|
||||||
|
if (!hasPositionTarget() && homePos.isPresent()) {
|
||||||
|
setPositionTarget(homePos.get(), (int)getAreaRadius());
|
||||||
|
}
|
||||||
|
|
||||||
|
setVelocity(Vec3d.ZERO);
|
||||||
super.tick();
|
super.tick();
|
||||||
|
|
||||||
if (getTarget() == null && getVelocity().y < 0) {
|
if (getTarget() == null && getVelocity().y < 0) {
|
||||||
setVelocity(getVelocity().multiply(1, 0.4, 1));
|
setVelocity(getVelocity().multiply(1, 0.4, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
addVelocity(0, 0.0242F, 0);
|
addVelocity(0, 0.0242F, 0);
|
||||||
|
|
||||||
|
if (isDead()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (isSubmergedInWater()) {
|
if (isSubmergedInWater()) {
|
||||||
jump();
|
jump();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (random.nextInt(1200) == 0) {
|
if (random.nextInt(1200) == 0) {
|
||||||
playSound(USounds.ENTITY_SOMBRA_LAUGH, 1, 1);
|
laugh();
|
||||||
getWorld().sendEntityStatus(this, BITE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (random.nextInt(340) == 0) {
|
if (random.nextInt(340) == 0) {
|
||||||
|
@ -235,9 +275,11 @@ public class SombraEntity extends HostileEntity implements ArenaCombatant, Parti
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (random.nextInt(200) == 0) {
|
||||||
for (BlockPos p : BlockPos.iterateRandomly(random, 3, getBlockPos(), 20)) {
|
for (BlockPos p : BlockPos.iterateRandomly(random, 3, getBlockPos(), 20)) {
|
||||||
CrystalShardsEntity.infestBlock((ServerWorld)getWorld(), p);
|
CrystalShardsEntity.infestBlock((ServerWorld)getWorld(), p);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (getTarget() == null && getNavigation().isIdle()) {
|
if (getTarget() == null && getNavigation().isIdle()) {
|
||||||
getNavigation().startMovingTo(homePos.get().getX(), homePos.get().getY() + 10, homePos.get().getZ(), 2);
|
getNavigation().startMovingTo(homePos.get().getX(), homePos.get().getY() + 10, homePos.get().getZ(), 2);
|
||||||
|
@ -247,6 +289,29 @@ public class SombraEntity extends HostileEntity implements ArenaCombatant, Parti
|
||||||
getHomePos().ifPresent(this::generateArenaEffects);
|
getHomePos().ifPresent(this::generateArenaEffects);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void tickGrowth(float targetSize, boolean changing) {
|
||||||
|
if (currentSize != targetSize) {
|
||||||
|
float sizeDifference = (dataTracker.get(TARGET_SIZE) - currentSize);
|
||||||
|
currentSize = Math.abs(sizeDifference) < 0.01F ? targetSize : currentSize + (sizeDifference * 0.2F);
|
||||||
|
calculateDimensions();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentSize == targetSize && changing) {
|
||||||
|
laugh();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentSize == targetSize && isDead()) {
|
||||||
|
setScaleFactor(currentSize + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void laugh() {
|
||||||
|
if (!getWorld().isClient) {
|
||||||
|
playSound(USounds.ENTITY_SOMBRA_LAUGH, 1, 1);
|
||||||
|
getWorld().sendEntityStatus(this, BITE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected void applyAreaEffects(Entity target) {
|
protected void applyAreaEffects(Entity target) {
|
||||||
if (this.age % 150 == 0) {
|
if (this.age % 150 == 0) {
|
||||||
target.playSound(
|
target.playSound(
|
||||||
|
@ -297,16 +362,6 @@ public class SombraEntity extends HostileEntity implements ArenaCombatant, Parti
|
||||||
ParticleUtils.spawnParticle(getWorld(), type, pos, Vec3d.ZERO);
|
ParticleUtils.spawnParticle(getWorld(), type, pos, Vec3d.ZERO);
|
||||||
ParticleUtils.spawnParticle(getWorld(), type, pos, pos.subtract(getPos()).add(0, 0.1, 0).multiply(-0.013));
|
ParticleUtils.spawnParticle(getWorld(), type, pos, pos.subtract(getPos()).add(0, 0.1, 0).multiply(-0.013));
|
||||||
});
|
});
|
||||||
|
|
||||||
shroud.update(getUuid(), this, spawner -> {
|
|
||||||
var radius = getAreaRadius();
|
|
||||||
var center = home.toCenterPos();
|
|
||||||
spawner.addParticle(new SphereParticleEffect(UParticles.SPHERE, 0xFF000000, 1, radius - 0.2F), center, Vec3d.ZERO);
|
|
||||||
}).ifPresent(attachment -> {
|
|
||||||
attachment.setAttribute(Attachment.ATTR_BOUND, 1);
|
|
||||||
attachment.setAttribute(Attachment.ATTR_COLOR, 0xFF000000);
|
|
||||||
attachment.setAttribute(Attachment.ATTR_OPACITY, 2.5F);
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
for (Entity target : VecHelper.findInRange(this, getWorld(), home.toCenterPos(), getAreaRadius() - 0.2F, EFFECT_TARGET_PREDICATE)) {
|
for (Entity target : VecHelper.findInRange(this, getWorld(), home.toCenterPos(), getAreaRadius() - 0.2F, EFFECT_TARGET_PREDICATE)) {
|
||||||
applyAreaEffects(target);
|
applyAreaEffects(target);
|
||||||
|
@ -352,10 +407,17 @@ public class SombraEntity extends HostileEntity implements ArenaCombatant, Parti
|
||||||
}
|
}
|
||||||
boolean damaged = super.damage(source, amount);
|
boolean damaged = super.damage(source, amount);
|
||||||
|
|
||||||
|
if (!getWorld().isClient) {
|
||||||
if (source.getAttacker() instanceof PlayerEntity player) {
|
if (source.getAttacker() instanceof PlayerEntity player) {
|
||||||
teleportRandomly(16);
|
teleportRandomly(16);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float targetSize = getScaleFactor();
|
||||||
|
if (targetSize > 1) {
|
||||||
|
setScaleFactor(Math.max(1, targetSize * 0.9F));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return damaged;
|
return damaged;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -376,6 +438,39 @@ public class SombraEntity extends HostileEntity implements ArenaCombatant, Parti
|
||||||
super.onDeath(damageSource);
|
super.onDeath(damageSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void updatePostDeath() {
|
||||||
|
if (++deathTime >= 180 && deathTime <= 200) {
|
||||||
|
getWorld().addParticle(ParticleTypes.EXPLOSION_EMITTER,
|
||||||
|
random.nextTriangular(getX(), 4F),
|
||||||
|
random.nextTriangular(getY() + 2, 2F),
|
||||||
|
random.nextTriangular(getZ(), 4F), 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
move(MovementType.SELF, new Vec3d(0, 0.3F, 0));
|
||||||
|
|
||||||
|
if (getWorld() instanceof ServerWorld sw) {
|
||||||
|
final boolean dropLoot = this.getWorld().getGameRules().getBoolean(GameRules.DO_MOB_LOOT);
|
||||||
|
final int experience = 500;
|
||||||
|
|
||||||
|
if (deathTime > 150 && deathTime % 5 == 0 && dropLoot) {
|
||||||
|
ExperienceOrbEntity.spawn(sw, getPos(), MathHelper.floor(experience * 0.08f));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deathTime == 1 && !isSilent()) {
|
||||||
|
getWorld().syncGlobalEvent(WorldEvents.ENDER_DRAGON_DIES, this.getBlockPos(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deathTime == 200) {
|
||||||
|
if (dropLoot) {
|
||||||
|
ExperienceOrbEntity.spawn(sw, getPos(), MathHelper.floor(experience * 0.2f));
|
||||||
|
}
|
||||||
|
remove(RemovalReason.KILLED);
|
||||||
|
emitGameEvent(GameEvent.ENTITY_DIE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void fall(double y, boolean onGroundIn, BlockState state, BlockPos pos) {
|
protected void fall(double y, boolean onGroundIn, BlockState state, BlockPos pos) {
|
||||||
}
|
}
|
||||||
|
@ -385,9 +480,16 @@ public class SombraEntity extends HostileEntity implements ArenaCombatant, Parti
|
||||||
return super.canTarget(target) && getHomePos().filter(home -> target.getPos().isInRange(home.toCenterPos(), getAreaRadius())).isPresent();
|
return super.canTarget(target) && getHomePos().filter(home -> target.getPos().isInRange(home.toCenterPos(), getAreaRadius())).isPresent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isInWalkTargetRange(BlockPos pos) {
|
||||||
|
BlockPos center = getHomePos().orElse(getBlockPos());
|
||||||
|
double distance = pos.getSquaredDistanceFromCenter(center.getX() + 0.5, center.getY() + 0.5, center.getZ() + 0.5);
|
||||||
|
return distance < MathHelper.square(getAreaRadius());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean tryAttack(Entity target) {
|
public boolean tryAttack(Entity target) {
|
||||||
getWorld().sendEntityStatus(this, BITE);
|
laugh();
|
||||||
return super.tryAttack(target);
|
return super.tryAttack(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -458,6 +560,7 @@ public class SombraEntity extends HostileEntity implements ArenaCombatant, Parti
|
||||||
nbt.put("homePos", pos);
|
nbt.put("homePos", pos);
|
||||||
});
|
});
|
||||||
nbt.put("cloud", stormCloud.toNBT());
|
nbt.put("cloud", stormCloud.toNBT());
|
||||||
|
nbt.putFloat("size", getScaleFactor());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -469,6 +572,24 @@ public class SombraEntity extends HostileEntity implements ArenaCombatant, Parti
|
||||||
if (hasCustomName()) {
|
if (hasCustomName()) {
|
||||||
bossBar.setName(getDisplayName());
|
bossBar.setName(getDisplayName());
|
||||||
}
|
}
|
||||||
|
setScaleFactor(nbt.getFloat("size"));
|
||||||
stormCloud.fromNBT(nbt.getCompound("cloud"));
|
stormCloud.fromNBT(nbt.getCompound("cloud"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class SombraBossBar extends ServerBossBar {
|
||||||
|
public SombraBossBar(Text displayName) {
|
||||||
|
super(displayName, BossBar.Color.PURPLE, BossBar.Style.PROGRESS);
|
||||||
|
setDarkenSky(true);
|
||||||
|
setThickenFog(true);
|
||||||
|
setDragonMusic(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPercent(float percent) {
|
||||||
|
super.setPercent(percent);
|
||||||
|
if (percent > 0.6F && getColor() == Color.PURPLE) {
|
||||||
|
setColor(Color.RED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
package com.minelittlepony.unicopia.entity;
|
package com.minelittlepony.unicopia.entity;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.USounds;
|
import com.minelittlepony.unicopia.USounds;
|
||||||
import com.minelittlepony.unicopia.particle.UParticles;
|
import com.minelittlepony.unicopia.particle.UParticles;
|
||||||
import com.minelittlepony.unicopia.server.world.WeatherConditions;
|
import com.minelittlepony.unicopia.server.world.WeatherConditions;
|
||||||
|
@ -9,13 +13,17 @@ import com.minelittlepony.unicopia.server.world.WeatherConditions;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.EntityType;
|
import net.minecraft.entity.EntityType;
|
||||||
import net.minecraft.entity.LightningEntity;
|
import net.minecraft.entity.LightningEntity;
|
||||||
|
import net.minecraft.entity.boss.ServerBossBar;
|
||||||
import net.minecraft.entity.damage.DamageSource;
|
import net.minecraft.entity.damage.DamageSource;
|
||||||
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.nbt.NbtCompound;
|
import net.minecraft.nbt.NbtCompound;
|
||||||
import net.minecraft.predicate.entity.EntityPredicates;
|
import net.minecraft.predicate.entity.EntityPredicates;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
import net.minecraft.server.world.ServerWorld;
|
import net.minecraft.server.world.ServerWorld;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import net.minecraft.util.Formatting;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.Direction;
|
import net.minecraft.util.math.Direction;
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
@ -29,6 +37,10 @@ public class StormCloudEntity extends Entity {
|
||||||
private static final TrackedData<Float> TARGET_SIZE = DataTracker.registerData(StormCloudEntity.class, TrackedDataHandlerRegistry.FLOAT);
|
private static final TrackedData<Float> TARGET_SIZE = DataTracker.registerData(StormCloudEntity.class, TrackedDataHandlerRegistry.FLOAT);
|
||||||
private static final TrackedData<Boolean> DISSIPATING = DataTracker.registerData(StormCloudEntity.class, TrackedDataHandlerRegistry.BOOLEAN);
|
private static final TrackedData<Boolean> DISSIPATING = DataTracker.registerData(StormCloudEntity.class, TrackedDataHandlerRegistry.BOOLEAN);
|
||||||
|
|
||||||
|
static final float MAX_SIZE = 30;
|
||||||
|
static final int CLEAR_TARGET_ALTITUDE = 90;
|
||||||
|
static final int STORMY_TARGET_ALTITUDE = 20;
|
||||||
|
|
||||||
private float prevSize;
|
private float prevSize;
|
||||||
private float currentSize;
|
private float currentSize;
|
||||||
|
|
||||||
|
@ -37,6 +49,10 @@ public class StormCloudEntity extends Entity {
|
||||||
private int phase;
|
private int phase;
|
||||||
private int nextPhase;
|
private int nextPhase;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private ServerBossBar bossBar;
|
||||||
|
private final Set<ServerPlayerEntity> trackingPlayers = new HashSet<>();
|
||||||
|
|
||||||
public StormCloudEntity(EntityType<StormCloudEntity> type, World world) {
|
public StormCloudEntity(EntityType<StormCloudEntity> type, World world) {
|
||||||
super(type, world);
|
super(type, world);
|
||||||
setSize(1 + random.nextInt(4));
|
setSize(1 + random.nextInt(4));
|
||||||
|
@ -88,7 +104,7 @@ public class StormCloudEntity extends Entity {
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getSize(float tickDelta) {
|
public float getSize(float tickDelta) {
|
||||||
return MathHelper.clamp(MathHelper.lerp(tickDelta, prevSize, currentSize), 1, 30);
|
return MathHelper.clamp(MathHelper.lerp(tickDelta, prevSize, currentSize), 1, MAX_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSize(float size) {
|
public void setSize(float size) {
|
||||||
|
@ -103,12 +119,11 @@ public class StormCloudEntity extends Entity {
|
||||||
public void tick() {
|
public void tick() {
|
||||||
setFireTicks(1);
|
setFireTicks(1);
|
||||||
|
|
||||||
|
|
||||||
prevSize = currentSize;
|
prevSize = currentSize;
|
||||||
float targetSize = dataTracker.get(TARGET_SIZE);
|
float targetSize = dataTracker.get(TARGET_SIZE);
|
||||||
if (currentSize != targetSize) {
|
if (currentSize != targetSize) {
|
||||||
float sizeDifference = (dataTracker.get(TARGET_SIZE) - currentSize);
|
float sizeDifference = (dataTracker.get(TARGET_SIZE) - currentSize);
|
||||||
currentSize = Math.abs(sizeDifference) < 0.01F ? targetSize : currentSize + (sizeDifference * 0.2F);
|
currentSize = Math.abs(sizeDifference) < 0.01F ? targetSize : currentSize + (sizeDifference * 0.02F);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isStormy()) {
|
if (isStormy()) {
|
||||||
|
@ -120,7 +135,7 @@ public class StormCloudEntity extends Entity {
|
||||||
|
|
||||||
if (isLogicalSideForUpdatingMovement()) {
|
if (isLogicalSideForUpdatingMovement()) {
|
||||||
float groundY = getWorld().getTopY(Type.MOTION_BLOCKING_NO_LEAVES, (int)getX(), (int)getZ());
|
float groundY = getWorld().getTopY(Type.MOTION_BLOCKING_NO_LEAVES, (int)getX(), (int)getZ());
|
||||||
float cloudY = (float)getY() - (isStormy() ? 20 : 90);
|
float cloudY = (float)getY() - (isStormy() ? STORMY_TARGET_ALTITUDE : CLEAR_TARGET_ALTITUDE);
|
||||||
|
|
||||||
addVelocity(0, 0.03F * (groundY - cloudY), 0);
|
addVelocity(0, 0.03F * (groundY - cloudY), 0);
|
||||||
|
|
||||||
|
@ -169,6 +184,11 @@ public class StormCloudEntity extends Entity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cursed) {
|
||||||
|
float percent = Math.min(1, (size + 1) / MAX_SIZE);
|
||||||
|
getBossBar().setPercent(percent);
|
||||||
|
}
|
||||||
|
|
||||||
if (currentSize == targetSize) {
|
if (currentSize == targetSize) {
|
||||||
if (isDissipating()) {
|
if (isDissipating()) {
|
||||||
if (size < 2) {
|
if (size < 2) {
|
||||||
|
@ -181,10 +201,11 @@ public class StormCloudEntity extends Entity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (size < 30) {
|
if (size < MAX_SIZE) {
|
||||||
if (cursed) {
|
if (cursed) {
|
||||||
setSize(size + 1);
|
setSize(size + 1);
|
||||||
setStormTicks(1);
|
setStormTicks(-1);
|
||||||
|
|
||||||
spawnLightningStrike(getBlockPos(), false, false);
|
spawnLightningStrike(getBlockPos(), false, false);
|
||||||
playSound(USounds.AMBIENT_WIND_GUST, 1, 1);
|
playSound(USounds.AMBIENT_WIND_GUST, 1, 1);
|
||||||
}
|
}
|
||||||
|
@ -192,7 +213,7 @@ public class StormCloudEntity extends Entity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size >= 30) {
|
if (size >= MAX_SIZE) {
|
||||||
if (cursed) {
|
if (cursed) {
|
||||||
setStormTicks(-1);
|
setStormTicks(-1);
|
||||||
|
|
||||||
|
@ -208,9 +229,10 @@ public class StormCloudEntity extends Entity {
|
||||||
pickRandomPoints(13, pos -> spawnLightningStrike(pos, true, false));
|
pickRandomPoints(13, pos -> spawnLightningStrike(pos, true, false));
|
||||||
|
|
||||||
cursed = false;
|
cursed = false;
|
||||||
SombraEntity sombra = UEntities.SOMBRA.create(getWorld());
|
SombraEntity sombra = new SombraEntity(UEntities.SOMBRA, getWorld(), getBossBar());
|
||||||
sombra.setPosition(getPos());
|
sombra.setPosition(getPos());
|
||||||
sombra.setHomePos(getWorld().getTopPosition(Type.MOTION_BLOCKING_NO_LEAVES, getBlockPos()));
|
sombra.setHomePos(getWorld().getTopPosition(Type.MOTION_BLOCKING_NO_LEAVES, getBlockPos()));
|
||||||
|
sombra.setScaleFactor(8);
|
||||||
sombra.stormCloud.set(this);
|
sombra.stormCloud.set(this);
|
||||||
getWorld().spawnEntity(sombra);
|
getWorld().spawnEntity(sombra);
|
||||||
|
|
||||||
|
@ -299,6 +321,15 @@ public class StormCloudEntity extends Entity {
|
||||||
super.handleStatus(status);
|
super.handleStatus(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ServerBossBar getBossBar() {
|
||||||
|
if (this.bossBar == null) {
|
||||||
|
this.bossBar = SombraEntity.createBossBar(Text.translatable("unicopia.entity.sombra").formatted(Formatting.OBFUSCATED));
|
||||||
|
trackingPlayers.removeIf(Entity::isRemoved);
|
||||||
|
trackingPlayers.forEach(this.bossBar::addPlayer);
|
||||||
|
}
|
||||||
|
return this.bossBar;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeCustomDataToNbt(NbtCompound nbt) {
|
public void writeCustomDataToNbt(NbtCompound nbt) {
|
||||||
nbt.putInt("stormTicks", getStormTicks());
|
nbt.putInt("stormTicks", getStormTicks());
|
||||||
|
@ -314,4 +345,25 @@ public class StormCloudEntity extends Entity {
|
||||||
setSize(currentSize = nbt.getFloat("size"));
|
setSize(currentSize = nbt.getFloat("size"));
|
||||||
cursed = nbt.getBoolean("cursed");
|
cursed = nbt.getBoolean("cursed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStartedTrackingBy(ServerPlayerEntity player) {
|
||||||
|
super.onStartedTrackingBy(player);
|
||||||
|
trackingPlayers.removeIf(Entity::isRemoved);
|
||||||
|
trackingPlayers.add(player);
|
||||||
|
if (bossBar != null) {
|
||||||
|
bossBar.addPlayer(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStoppedTrackingBy(ServerPlayerEntity player) {
|
||||||
|
super.onStoppedTrackingBy(player);
|
||||||
|
trackingPlayers.removeIf(Entity::isRemoved);
|
||||||
|
trackingPlayers.remove(player);
|
||||||
|
if (bossBar != null) {
|
||||||
|
bossBar.removePlayer(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,15 +46,15 @@ public interface UEntities {
|
||||||
EntityType<SpellbookEntity> SPELLBOOK = register("spellbook", FabricEntityTypeBuilder.create(SpawnGroup.MISC, SpellbookEntity::new)
|
EntityType<SpellbookEntity> SPELLBOOK = register("spellbook", FabricEntityTypeBuilder.create(SpawnGroup.MISC, SpellbookEntity::new)
|
||||||
.trackRangeBlocks(200)
|
.trackRangeBlocks(200)
|
||||||
.dimensions(EntityDimensions.fixed(0.9F, 0.5F)));
|
.dimensions(EntityDimensions.fixed(0.9F, 0.5F)));
|
||||||
EntityType<SombraEntity> SOMBRA = register("sombra", FabricEntityTypeBuilder.create(SpawnGroup.MONSTER, SombraEntity::new)
|
EntityType<SombraEntity> SOMBRA = register("sombra", FabricEntityTypeBuilder.<SombraEntity>create(SpawnGroup.MONSTER, SombraEntity::new)
|
||||||
.trackRangeBlocks(200)
|
.trackRangeBlocks(20)
|
||||||
.dimensions(EntityDimensions.fixed(1F, 2F)));
|
.dimensions(EntityDimensions.changing(2F, 4F)));
|
||||||
EntityType<CrystalShardsEntity> CRYSTAL_SHARDS = register("crystal_shards", FabricEntityTypeBuilder.create(SpawnGroup.MISC, CrystalShardsEntity::new)
|
EntityType<CrystalShardsEntity> CRYSTAL_SHARDS = register("crystal_shards", FabricEntityTypeBuilder.create(SpawnGroup.MISC, CrystalShardsEntity::new)
|
||||||
.trackRangeBlocks(100)
|
.trackRangeBlocks(100)
|
||||||
.dimensions(EntityDimensions.fixed(1F, 1F)));
|
.dimensions(EntityDimensions.changing(1F, 1F)));
|
||||||
EntityType<StormCloudEntity> STORM_CLOUD = register("storm_cloud", FabricEntityTypeBuilder.create(SpawnGroup.MISC, StormCloudEntity::new)
|
EntityType<StormCloudEntity> STORM_CLOUD = register("storm_cloud", FabricEntityTypeBuilder.create(SpawnGroup.MISC, StormCloudEntity::new)
|
||||||
.trackRangeBlocks(200)
|
.trackRangeBlocks(200)
|
||||||
.dimensions(EntityDimensions.fixed(20F, 20F)));
|
.dimensions(EntityDimensions.changing(20F, 20F)));
|
||||||
EntityType<AirBalloonEntity> AIR_BALLOON = register("air_balloon", FabricEntityTypeBuilder.create(SpawnGroup.MISC, AirBalloonEntity::new)
|
EntityType<AirBalloonEntity> AIR_BALLOON = register("air_balloon", FabricEntityTypeBuilder.create(SpawnGroup.MISC, AirBalloonEntity::new)
|
||||||
.trackRangeBlocks(1000)
|
.trackRangeBlocks(1000)
|
||||||
.dimensions(EntityDimensions.changing(2.5F, 0.1F)));
|
.dimensions(EntityDimensions.changing(2.5F, 0.1F)));
|
||||||
|
|
|
@ -223,7 +223,10 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
|
||||||
*/
|
*/
|
||||||
public Race.Composite getCompositeRace() {
|
public Race.Composite getCompositeRace() {
|
||||||
Race observed = getObservedSpecies();
|
Race observed = getObservedSpecies();
|
||||||
return new Race.Composite(observed, AmuletSelectors.ALICORN_AMULET.test(entity) ? Race.ALICORN : observed);
|
return new Race.Composite(observed,
|
||||||
|
AmuletSelectors.UNICORN_AMULET.test(entity) ? Race.UNICORN
|
||||||
|
: AmuletSelectors.ALICORN_AMULET.test(entity) ? Race.ALICORN
|
||||||
|
: observed);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -142,6 +142,11 @@ public interface UItems {
|
||||||
.maxCount(1)
|
.maxCount(1)
|
||||||
.maxDamage(1000)
|
.maxDamage(1000)
|
||||||
.rarity(Rarity.RARE)), ItemGroups.TOOLS);
|
.rarity(Rarity.RARE)), ItemGroups.TOOLS);
|
||||||
|
Item BROKEN_ALICORN_AMULET = register("broken_alicorn_amulet", new Item(new Item.Settings()), ItemGroups.TOOLS);
|
||||||
|
AmuletItem UNICORN_AMULET = register("unicorn_amulet", new AmuletItem(new FabricItemSettings()
|
||||||
|
.maxCount(1)
|
||||||
|
.maxDamage(890)
|
||||||
|
.rarity(Rarity.UNCOMMON), 900), ItemGroups.TOOLS);
|
||||||
|
|
||||||
GlassesItem SUNGLASSES = register("sunglasses", new GlassesItem(new FabricItemSettings().maxCount(1)), ItemGroups.COMBAT);
|
GlassesItem SUNGLASSES = register("sunglasses", new GlassesItem(new FabricItemSettings().maxCount(1)), ItemGroups.COMBAT);
|
||||||
GlassesItem BROKEN_SUNGLASSES = register("broken_sunglasses", new GlassesItem(new FabricItemSettings().maxCount(1)), ItemGroups.COMBAT);
|
GlassesItem BROKEN_SUNGLASSES = register("broken_sunglasses", new GlassesItem(new FabricItemSettings().maxCount(1)), ItemGroups.COMBAT);
|
||||||
|
|
|
@ -124,6 +124,10 @@
|
||||||
"item.unicopia.alicorn_amulet": "Alicorn Amulet",
|
"item.unicopia.alicorn_amulet": "Alicorn Amulet",
|
||||||
"item.unicopia.alicorn_amulet.lore": "Time worn: %d",
|
"item.unicopia.alicorn_amulet.lore": "Time worn: %d",
|
||||||
|
|
||||||
|
"item.unicopia.broken_alicorn_amulet": "Broken Alicorn Amulet",
|
||||||
|
"item.unicopia.unicorn_amulet": "Unicorn Amulet",
|
||||||
|
"item.unicopia.unicorn_amulet.lore": "Grants magical abilities to whoever wears it",
|
||||||
|
|
||||||
"item.unicopia.grogars_bell": "Grogar's Bell",
|
"item.unicopia.grogars_bell": "Grogar's Bell",
|
||||||
"item.unicopia.grogars_bell.charges": "Charges: %d / %d",
|
"item.unicopia.grogars_bell.charges": "Charges: %d / %d",
|
||||||
"item.unicopia.magic_staff": "Magic Staff",
|
"item.unicopia.magic_staff": "Magic Staff",
|
||||||
|
@ -197,8 +201,12 @@
|
||||||
"entity.unicopia.cast_spell": "Cast Spell",
|
"entity.unicopia.cast_spell": "Cast Spell",
|
||||||
"entity.unicopia.cast_spell.by": "a spell cast by %s",
|
"entity.unicopia.cast_spell.by": "a spell cast by %s",
|
||||||
"entity.unicopia.spellbook": "Spellbook",
|
"entity.unicopia.spellbook": "Spellbook",
|
||||||
|
"entity.unicopia.air_balloon": "Hot Air Balloon",
|
||||||
"entity.unicopia.sombra": "King Sombra",
|
"entity.unicopia.sombra": "King Sombra",
|
||||||
"entity.unicopia.sombra.taunt": "That's not going to work on me!",
|
"entity.unicopia.sombra.taunt": "That's not going to work on me!",
|
||||||
|
"entity.unicopia.storm_cloud": "Storm Cloud",
|
||||||
|
"entity.unicopia.sombra": "King Sombra",
|
||||||
|
"entity.unicopia.crystal_shards": "Crystal Shards",
|
||||||
|
|
||||||
"player.reachDistance": "Reach Distance",
|
"player.reachDistance": "Reach Distance",
|
||||||
"player.miningSpeed": "Mining Speed",
|
"player.miningSpeed": "Mining Speed",
|
||||||
|
|
|
@ -1,18 +1,6 @@
|
||||||
{
|
{
|
||||||
"parent": "item/generated",
|
"parent": "unicopia:item/amulet",
|
||||||
"textures": {
|
"textures": {
|
||||||
"layer0": "unicopia:item/alicorn_amulet"
|
"layer0": "unicopia:item/alicorn_amulet"
|
||||||
},
|
|
||||||
"display": {
|
|
||||||
"thirdperson": {
|
|
||||||
"rotation": [ -90, 0, 0 ],
|
|
||||||
"translation": [ 0, 1, -3 ],
|
|
||||||
"scale": [ 0.55, 0.55, 0.55 ]
|
|
||||||
},
|
|
||||||
"firstperson": {
|
|
||||||
"rotation": [ 0, -135, 25 ],
|
|
||||||
"translation": [ 0, 4, 2 ],
|
|
||||||
"scale": [ 1.7, 1.7, 1.7 ]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
15
src/main/resources/assets/unicopia/models/item/amulet.json
Normal file
15
src/main/resources/assets/unicopia/models/item/amulet.json
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"parent": "item/generated",
|
||||||
|
"display": {
|
||||||
|
"thirdperson": {
|
||||||
|
"rotation": [ -90, 0, 0 ],
|
||||||
|
"translation": [ 0, 1, -3 ],
|
||||||
|
"scale": [ 0.55, 0.55, 0.55 ]
|
||||||
|
},
|
||||||
|
"firstperson": {
|
||||||
|
"rotation": [ 0, -135, 25 ],
|
||||||
|
"translation": [ 0, 4, 2 ],
|
||||||
|
"scale": [ 1.7, 1.7, 1.7 ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"parent": "item/generated",
|
||||||
|
"textures": {
|
||||||
|
"layer0": "unicopia:item/broken_alicorn_amulet"
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"parent": "item/generated",
|
"parent": "unicopia:item/amulet",
|
||||||
"textures": {
|
"textures": {
|
||||||
"layer0": "unicopia:item/pegasus_amulet"
|
"layer0": "unicopia:item/pegasus_amulet"
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"parent": "unicopia:item/amulet",
|
||||||
|
"textures": {
|
||||||
|
"layer0": "unicopia:item/unicorn_amulet"
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
Before Width: | Height: | Size: 549 B After Width: | Height: | Size: 4.5 KiB |
Binary file not shown.
After Width: | Height: | Size: 4.5 KiB |
Binary file not shown.
After Width: | Height: | Size: 4.5 KiB |
|
@ -2,6 +2,7 @@
|
||||||
"replace": false,
|
"replace": false,
|
||||||
"values": [
|
"values": [
|
||||||
"unicopia:alicorn_amulet",
|
"unicopia:alicorn_amulet",
|
||||||
"unicopia:pegasus_amulet"
|
"unicopia:pegasus_amulet",
|
||||||
|
"unicopia:unicorn_amulet"
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -9,9 +9,11 @@
|
||||||
"unicopia:magic_staff",
|
"unicopia:magic_staff",
|
||||||
"unicopia:dragon_breath_scroll",
|
"unicopia:dragon_breath_scroll",
|
||||||
"unicopia:spellbook",
|
"unicopia:spellbook",
|
||||||
|
"unicopia:meadowbrooks_staff",
|
||||||
|
"unicopia:grogars_bell",
|
||||||
"unicopia:pegasus_amulet",
|
"unicopia:pegasus_amulet",
|
||||||
"unicopia:alicorn_amulet",
|
"unicopia:alicorn_amulet",
|
||||||
"unicopia:meadowbrooks_staff",
|
"unicopia:broken_alicorn_amulet",
|
||||||
"unicopia:grogars_bell"
|
"unicopia:unicorn_amulet"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue