Add broken alicorn amulet, and further tweaks the sombra

This commit is contained in:
Sollace 2023-08-26 16:16:31 +01:00
parent 30c91050db
commit 0320976d47
No known key found for this signature in database
GPG key ID: E52FACE7B5C773DB
20 changed files with 284 additions and 71 deletions

View file

@ -83,7 +83,13 @@ public class SombraEntityModel extends EntityModel<SombraEntity> {
@Override
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.pivotY -= jawsOpenAmount * 3;
@ -96,14 +102,8 @@ public class SombraEntityModel extends EntityModel<SombraEntity> {
@Override
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.pivotY = MathHelper.sin(animationProgress * 0.05F) - 12;
part.pivotY += MathHelper.sin(animationProgress * 0.05F);
part.pivotZ = MathHelper.cos(animationProgress * 0.045F);
head.pitch = headPitch * MathHelper.RADIANS_PER_DEGREE;

View file

@ -9,6 +9,7 @@ import net.minecraft.entity.LivingEntity;
public interface AmuletSelectors {
Predicate<LivingEntity> ALICORN_AMULET = UItems.ALICORN_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_2_DAYS = ALICORN_AMULET.and(ItemTracker.wearing(UItems.ALICORN_AMULET, ItemTracker.after(2 * ItemTracker.DAYS)));

View file

@ -120,6 +120,11 @@ public class Creature extends Living<LivingEntity> implements WeaklyOwned.Mutabl
}
public void initAi(GoalSelector goals, GoalSelector targets) {
if (entity instanceof SombraEntity) {
return;
}
this.goals = Optional.of(goals);
this.targets = Optional.of(targets);

View file

@ -63,7 +63,7 @@ public class CrystalShardsEntity extends Entity {
}
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()
.map(e -> e.getAttachmentFace())
.distinct()

View file

@ -10,19 +10,17 @@ import com.minelittlepony.unicopia.USounds;
import com.minelittlepony.unicopia.entity.ai.ArenaAttackGoal;
import com.minelittlepony.unicopia.item.AmuletItem;
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.ParticleUtils;
import com.minelittlepony.unicopia.particle.SphereParticleEffect;
import com.minelittlepony.unicopia.particle.UParticles;
import com.minelittlepony.unicopia.util.VecHelper;
import com.minelittlepony.unicopia.util.shape.Sphere;
import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.ExperienceOrbEntity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.MovementType;
import net.minecraft.entity.ai.goal.ActiveTargetGoal;
import net.minecraft.entity.ai.goal.FlyGoal;
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.boss.BossBar;
import net.minecraft.entity.boss.ServerBossBar;
import net.minecraft.entity.boss.BossBar.Style;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.data.DataTracker;
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.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.GameRules;
import net.minecraft.world.World;
import net.minecraft.world.WorldEvents;
import net.minecraft.world.event.GameEvent;
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);
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)
.setDarkenSky(true)
.setThickenFog(true);
private final ParticleHandle shroud = new ParticleHandle();
private final ServerBossBar bossBar;
final EntityReference<StormCloudEntity> stormCloud = new EntityReference<>();
private int prevBiteTime;
private int biteTime;
private float prevSize;
private float currentSize;
public static void startEncounter(World world, BlockPos pos) {
StormCloudEntity cloud = UEntities.STORM_CLOUD.create(world);
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) {
this(type, world, null);
}
public SombraEntity(EntityType<SombraEntity> type, World world, @Nullable ServerBossBar bossBar) {
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() {
@ -137,6 +147,7 @@ public class SombraEntity extends HostileEntity implements ArenaCombatant, Parti
protected void initDataTracker() {
super.initDataTracker();
dataTracker.startTracking(HOME_POS, Optional.empty());
dataTracker.startTracking(TARGET_SIZE, 1F);
}
@Override
@ -182,7 +193,21 @@ public class SombraEntity extends HostileEntity implements ArenaCombatant, Parti
public float getBiteAmount(float tickDelta) {
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
@ -191,8 +216,8 @@ public class SombraEntity extends HostileEntity implements ArenaCombatant, Parti
Optional<BlockPos> homePos = getHomePos();
if (homePos.isEmpty() && !isRemoved()) {
remove(RemovalReason.DISCARDED);
return;
setHomePos(getBlockPos());
homePos = getHomePos();
}
if (getBlockPos().getSquaredDistance(homePos.get()) > MathHelper.square(getAreaRadius())) {
@ -205,19 +230,34 @@ public class SombraEntity extends HostileEntity implements ArenaCombatant, Parti
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();
if (getTarget() == null && getVelocity().y < 0) {
setVelocity(getVelocity().multiply(1, 0.4, 1));
}
addVelocity(0, 0.0242F, 0);
if (isDead()) {
return;
}
if (isSubmergedInWater()) {
jump();
}
if (random.nextInt(1200) == 0) {
playSound(USounds.ENTITY_SOMBRA_LAUGH, 1, 1);
getWorld().sendEntityStatus(this, BITE);
laugh();
}
if (random.nextInt(340) == 0) {
@ -235,8 +275,10 @@ public class SombraEntity extends HostileEntity implements ArenaCombatant, Parti
}
}
for (BlockPos p : BlockPos.iterateRandomly(random, 3, getBlockPos(), 20)) {
CrystalShardsEntity.infestBlock((ServerWorld)getWorld(), p);
if (random.nextInt(200) == 0) {
for (BlockPos p : BlockPos.iterateRandomly(random, 3, getBlockPos(), 20)) {
CrystalShardsEntity.infestBlock((ServerWorld)getWorld(), p);
}
}
if (getTarget() == null && getNavigation().isIdle()) {
@ -247,6 +289,29 @@ public class SombraEntity extends HostileEntity implements ArenaCombatant, Parti
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) {
if (this.age % 150 == 0) {
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, 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 {
for (Entity target : VecHelper.findInRange(this, getWorld(), home.toCenterPos(), getAreaRadius() - 0.2F, EFFECT_TARGET_PREDICATE)) {
applyAreaEffects(target);
@ -352,8 +407,15 @@ public class SombraEntity extends HostileEntity implements ArenaCombatant, Parti
}
boolean damaged = super.damage(source, amount);
if (source.getAttacker() instanceof PlayerEntity player) {
teleportRandomly(16);
if (!getWorld().isClient) {
if (source.getAttacker() instanceof PlayerEntity player) {
teleportRandomly(16);
}
float targetSize = getScaleFactor();
if (targetSize > 1) {
setScaleFactor(Math.max(1, targetSize * 0.9F));
}
}
return damaged;
@ -376,6 +438,39 @@ public class SombraEntity extends HostileEntity implements ArenaCombatant, Parti
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
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();
}
@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
public boolean tryAttack(Entity target) {
getWorld().sendEntityStatus(this, BITE);
laugh();
return super.tryAttack(target);
}
@ -458,6 +560,7 @@ public class SombraEntity extends HostileEntity implements ArenaCombatant, Parti
nbt.put("homePos", pos);
});
nbt.put("cloud", stormCloud.toNBT());
nbt.putFloat("size", getScaleFactor());
}
@Override
@ -469,6 +572,24 @@ public class SombraEntity extends HostileEntity implements ArenaCombatant, Parti
if (hasCustomName()) {
bossBar.setName(getDisplayName());
}
setScaleFactor(nbt.getFloat("size"));
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);
}
}
}
}

View file

@ -1,7 +1,11 @@
package com.minelittlepony.unicopia.entity;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Consumer;
import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.USounds;
import com.minelittlepony.unicopia.particle.UParticles;
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.EntityType;
import net.minecraft.entity.LightningEntity;
import net.minecraft.entity.boss.ServerBossBar;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.data.DataTracker;
import net.minecraft.entity.data.TrackedData;
import net.minecraft.entity.data.TrackedDataHandlerRegistry;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.predicate.entity.EntityPredicates;
import net.minecraft.server.network.ServerPlayerEntity;
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.Direction;
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<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 currentSize;
@ -37,6 +49,10 @@ public class StormCloudEntity extends Entity {
private int phase;
private int nextPhase;
@Nullable
private ServerBossBar bossBar;
private final Set<ServerPlayerEntity> trackingPlayers = new HashSet<>();
public StormCloudEntity(EntityType<StormCloudEntity> type, World world) {
super(type, world);
setSize(1 + random.nextInt(4));
@ -88,7 +104,7 @@ public class StormCloudEntity extends Entity {
}
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) {
@ -103,12 +119,11 @@ public class StormCloudEntity extends Entity {
public void tick() {
setFireTicks(1);
prevSize = currentSize;
float targetSize = dataTracker.get(TARGET_SIZE);
if (currentSize != targetSize) {
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()) {
@ -120,7 +135,7 @@ public class StormCloudEntity extends Entity {
if (isLogicalSideForUpdatingMovement()) {
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);
@ -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 (isDissipating()) {
if (size < 2) {
@ -181,10 +201,11 @@ public class StormCloudEntity extends Entity {
}
}
} else {
if (size < 30) {
if (size < MAX_SIZE) {
if (cursed) {
setSize(size + 1);
setStormTicks(1);
setStormTicks(-1);
spawnLightningStrike(getBlockPos(), false, false);
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) {
setStormTicks(-1);
@ -208,9 +229,10 @@ public class StormCloudEntity extends Entity {
pickRandomPoints(13, pos -> spawnLightningStrike(pos, true, false));
cursed = false;
SombraEntity sombra = UEntities.SOMBRA.create(getWorld());
SombraEntity sombra = new SombraEntity(UEntities.SOMBRA, getWorld(), getBossBar());
sombra.setPosition(getPos());
sombra.setHomePos(getWorld().getTopPosition(Type.MOTION_BLOCKING_NO_LEAVES, getBlockPos()));
sombra.setScaleFactor(8);
sombra.stormCloud.set(this);
getWorld().spawnEntity(sombra);
@ -299,6 +321,15 @@ public class StormCloudEntity extends Entity {
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
public void writeCustomDataToNbt(NbtCompound nbt) {
nbt.putInt("stormTicks", getStormTicks());
@ -314,4 +345,25 @@ public class StormCloudEntity extends Entity {
setSize(currentSize = nbt.getFloat("size"));
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);
}
}
}

View file

@ -46,15 +46,15 @@ public interface UEntities {
EntityType<SpellbookEntity> SPELLBOOK = register("spellbook", FabricEntityTypeBuilder.create(SpawnGroup.MISC, SpellbookEntity::new)
.trackRangeBlocks(200)
.dimensions(EntityDimensions.fixed(0.9F, 0.5F)));
EntityType<SombraEntity> SOMBRA = register("sombra", FabricEntityTypeBuilder.create(SpawnGroup.MONSTER, SombraEntity::new)
.trackRangeBlocks(200)
.dimensions(EntityDimensions.fixed(1F, 2F)));
EntityType<SombraEntity> SOMBRA = register("sombra", FabricEntityTypeBuilder.<SombraEntity>create(SpawnGroup.MONSTER, SombraEntity::new)
.trackRangeBlocks(20)
.dimensions(EntityDimensions.changing(2F, 4F)));
EntityType<CrystalShardsEntity> CRYSTAL_SHARDS = register("crystal_shards", FabricEntityTypeBuilder.create(SpawnGroup.MISC, CrystalShardsEntity::new)
.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)
.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)
.trackRangeBlocks(1000)
.dimensions(EntityDimensions.changing(2.5F, 0.1F)));

View file

@ -223,7 +223,10 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
*/
public Race.Composite getCompositeRace() {
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);
}
/**

View file

@ -142,6 +142,11 @@ public interface UItems {
.maxCount(1)
.maxDamage(1000)
.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 BROKEN_SUNGLASSES = register("broken_sunglasses", new GlassesItem(new FabricItemSettings().maxCount(1)), ItemGroups.COMBAT);

View file

@ -123,6 +123,10 @@
"item.unicopia.alicorn_amulet": "Alicorn Amulet",
"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.charges": "Charges: %d / %d",
@ -197,8 +201,12 @@
"entity.unicopia.cast_spell": "Cast Spell",
"entity.unicopia.cast_spell.by": "a spell cast by %s",
"entity.unicopia.spellbook": "Spellbook",
"entity.unicopia.air_balloon": "Hot Air Balloon",
"entity.unicopia.sombra": "King Sombra",
"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.miningSpeed": "Mining Speed",

View file

@ -1,18 +1,6 @@
{
"parent": "item/generated",
"parent": "unicopia:item/amulet",
"textures": {
"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 ]
}
}
}

View 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 ]
}
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "unicopia:item/broken_alicorn_amulet"
}
}

View file

@ -1,5 +1,5 @@
{
"parent": "item/generated",
"parent": "unicopia:item/amulet",
"textures": {
"layer0": "unicopia:item/pegasus_amulet"
}

View file

@ -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

View file

@ -2,6 +2,7 @@
"replace": false,
"values": [
"unicopia:alicorn_amulet",
"unicopia:pegasus_amulet"
"unicopia:pegasus_amulet",
"unicopia:unicorn_amulet"
]
}

View file

@ -9,9 +9,11 @@
"unicopia:magic_staff",
"unicopia:dragon_breath_scroll",
"unicopia:spellbook",
"unicopia:meadowbrooks_staff",
"unicopia:grogars_bell",
"unicopia:pegasus_amulet",
"unicopia:alicorn_amulet",
"unicopia:meadowbrooks_staff",
"unicopia:grogars_bell"
"unicopia:broken_alicorn_amulet",
"unicopia:unicorn_amulet"
]
}