mirror of
https://github.com/Sollace/Unicopia.git
synced 2024-11-27 15:17:59 +01:00
Merge branch '1.20.1' of https://github.com/LingVarr/Unicopia into 1.20.1
This commit is contained in:
commit
e1cc467b05
43 changed files with 618 additions and 226 deletions
|
@ -33,7 +33,7 @@ public interface EquinePredicates {
|
|||
Predicate<Entity> IS_CASTER = e -> !e.isRemoved() && (e instanceof Caster || IS_PLAYER.test(e));
|
||||
Predicate<Entity> IS_PLACED_SPELL = e -> e instanceof Caster && !e.isRemoved();
|
||||
|
||||
Predicate<Entity> IS_MAGIC_IMMUNE = e -> (e instanceof MagicImmune || !(e instanceof LivingEntity)) && !(e instanceof ItemEntity);
|
||||
Predicate<Entity> IS_MAGIC_IMMUNE = e -> (e instanceof MagicImmune || !(e instanceof LivingEntity)) && !(e instanceof ItemEntity) && !(e instanceof ExperienceOrbEntity);
|
||||
Predicate<Entity> EXCEPT_MAGIC_IMMUNE = IS_MAGIC_IMMUNE.negate();
|
||||
Predicate<Entity> VALID_LIVING_AND_NOT_MAGIC_IMMUNE = EntityPredicates.VALID_LIVING_ENTITY.and(EXCEPT_MAGIC_IMMUNE);
|
||||
|
||||
|
|
|
@ -13,10 +13,6 @@ import com.minelittlepony.unicopia.entity.mob.UEntities;
|
|||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
import com.minelittlepony.unicopia.network.Channel;
|
||||
import com.minelittlepony.unicopia.network.MsgCasterLookRequest;
|
||||
import com.minelittlepony.unicopia.particle.OrientedBillboardParticleEffect;
|
||||
import com.minelittlepony.unicopia.particle.ParticleHandle;
|
||||
import com.minelittlepony.unicopia.particle.UParticles;
|
||||
import com.minelittlepony.unicopia.particle.ParticleHandle.Attachment;
|
||||
import com.minelittlepony.unicopia.server.world.Ether;
|
||||
import com.minelittlepony.unicopia.util.NbtSerialisable;
|
||||
|
||||
|
@ -24,6 +20,7 @@ import net.minecraft.nbt.*;
|
|||
import net.minecraft.registry.*;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
|
@ -40,11 +37,6 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS
|
|||
@Nullable
|
||||
private RegistryKey<World> dimension;
|
||||
|
||||
/**
|
||||
* The visual effect
|
||||
*/
|
||||
private final ParticleHandle particlEffect = new ParticleHandle();
|
||||
|
||||
/**
|
||||
* ID of the placed counterpart of this spell.
|
||||
*/
|
||||
|
@ -64,6 +56,9 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS
|
|||
public float pitch;
|
||||
public float yaw;
|
||||
|
||||
private int prevAge;
|
||||
private int age;
|
||||
|
||||
private Optional<Vec3d> position = Optional.empty();
|
||||
|
||||
public PlaceableSpell(CustomisedSpellType<?> type) {
|
||||
|
@ -75,15 +70,13 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Spell> getDelegates() {
|
||||
return List.of(spell);
|
||||
public float getAge(float tickDelta) {
|
||||
return MathHelper.lerp(tickDelta, prevAge, age);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDead() {
|
||||
super.setDead();
|
||||
particlEffect.destroy();
|
||||
public Collection<Spell> getDelegates() {
|
||||
return List.of(spell);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -115,14 +108,11 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS
|
|||
}
|
||||
}
|
||||
|
||||
if (spell instanceof PlacementDelegate delegate) {
|
||||
delegate.updatePlacement(source, this);
|
||||
prevAge = age;
|
||||
if (age < 25) {
|
||||
age++;
|
||||
}
|
||||
|
||||
getParticleEffectAttachment(source).ifPresent(p -> {
|
||||
p.setAttribute(Attachment.ATTR_COLOR, spell.getType().getColor());
|
||||
});
|
||||
|
||||
return super.tick(source, Situation.GROUND);
|
||||
}
|
||||
|
||||
|
@ -200,12 +190,6 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS
|
|||
return castEntity.getTarget().map(EntityValues::pos);
|
||||
}
|
||||
|
||||
public Optional<Attachment> getParticleEffectAttachment(Caster<?> source) {
|
||||
return particlEffect.update(getUuid(), source, spawner -> {
|
||||
spawner.addParticle(new OrientedBillboardParticleEffect(UParticles.MAGIC_RUNES, pitch + 90, yaw), Vec3d.ZERO, Vec3d.ZERO);
|
||||
});
|
||||
}
|
||||
|
||||
protected Optional<World> getWorld(Caster<?> source) {
|
||||
return Optional.ofNullable(dimension)
|
||||
.map(dim -> source.asWorld().getServer().getWorld(dim));
|
||||
|
@ -214,11 +198,15 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS
|
|||
@Override
|
||||
public void toNBT(NbtCompound compound) {
|
||||
super.toNBT(compound);
|
||||
compound.putInt("age", age);
|
||||
compound.putFloat("pitch", pitch);
|
||||
compound.putFloat("yaw", yaw);
|
||||
position.ifPresent(pos -> {
|
||||
compound.put("position", NbtSerialisable.writeVector(pos));
|
||||
});
|
||||
if (placedSpellId != null) {
|
||||
compound.putUuid("placedSpellId", placedSpellId);
|
||||
}
|
||||
if (dimension != null) {
|
||||
compound.putString("dimension", dimension.getValue().toString());
|
||||
}
|
||||
|
@ -229,9 +217,11 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS
|
|||
@Override
|
||||
public void fromNBT(NbtCompound compound) {
|
||||
super.fromNBT(compound);
|
||||
age = compound.getInt("age");
|
||||
pitch = compound.getFloat("pitch");
|
||||
yaw = compound.getFloat("yaw");
|
||||
position = compound.contains("position") ? Optional.of(NbtSerialisable.readVector(compound.getList("position", NbtElement.FLOAT_TYPE))) : Optional.empty();
|
||||
placedSpellId = compound.containsUuid("placedSpellId") ? compound.getUuid("placedSpellId") : null;
|
||||
if (compound.contains("dimension", NbtElement.STRING_TYPE)) {
|
||||
Identifier id = Identifier.tryParse(compound.getString("dimension"));
|
||||
if (id != null) {
|
||||
|
@ -260,9 +250,6 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS
|
|||
}
|
||||
|
||||
public interface PlacementDelegate {
|
||||
|
||||
void onPlaced(Caster<?> source, PlaceableSpell parent, CastSpellEntity entity);
|
||||
|
||||
void updatePlacement(Caster<?> source, PlaceableSpell parent);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ public class RainboomAbilitySpell extends AbstractSpell {
|
|||
});
|
||||
|
||||
if (source.isClient()) {
|
||||
// source.addParticle(new OrientedBillboardParticleEffect(UParticles.RAINBOOM_RING, source.getPhysics().getMotionAngle()), source.getOriginVector(), Vec3d.ZERO);
|
||||
//source.addParticle(new OrientedBillboardParticleEffect(UParticles.RAINBOOM_RING, source.getPhysics().getMotionAngle()), source.getOriginVector(), Vec3d.ZERO);
|
||||
}
|
||||
|
||||
source.findAllEntitiesInRange(RADIUS).forEach(e -> {
|
||||
|
|
|
@ -29,7 +29,7 @@ public interface TimedSpell extends Spell {
|
|||
}
|
||||
|
||||
public float getPercentTimeRemaining(float tickDelta) {
|
||||
return MathHelper.lerp(tickDelta, prevDuration, duration) / maxDuration;
|
||||
return MathHelper.lerp(tickDelta, prevDuration, duration) / (float)maxDuration;
|
||||
}
|
||||
|
||||
public int getTicksRemaining() {
|
||||
|
|
|
@ -7,7 +7,6 @@ import com.minelittlepony.unicopia.entity.EntityReference;
|
|||
import com.minelittlepony.unicopia.entity.Living;
|
||||
import com.minelittlepony.unicopia.entity.damage.UDamageTypes;
|
||||
import com.minelittlepony.unicopia.particle.FollowingParticleEffect;
|
||||
import com.minelittlepony.unicopia.particle.MagicParticleEffect;
|
||||
import com.minelittlepony.unicopia.particle.UParticles;
|
||||
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
|
||||
import com.minelittlepony.unicopia.projectile.ProjectileDelegate;
|
||||
|
@ -16,6 +15,7 @@ import com.minelittlepony.unicopia.util.shape.Sphere;
|
|||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.ItemEntity;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.particle.ParticleTypes;
|
||||
import net.minecraft.util.hit.EntityHitResult;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
@ -44,9 +44,10 @@ public class AttractiveSpell extends ShieldSpell implements HomingSpell, TimedSp
|
|||
if (timer.getTicksRemaining() <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
setDirty();
|
||||
}
|
||||
|
||||
setDirty();
|
||||
target.getOrEmpty(caster.asWorld())
|
||||
.filter(entity -> entity.distanceTo(caster.asEntity()) > getDrawDropOffRange(caster))
|
||||
.ifPresent(entity -> {
|
||||
|
@ -59,12 +60,13 @@ public class AttractiveSpell extends ShieldSpell implements HomingSpell, TimedSp
|
|||
|
||||
@Override
|
||||
public void generateParticles(Caster<?> source) {
|
||||
double range = getDrawDropOffRange(source) + 10;
|
||||
double range = getDrawDropOffRange(source);
|
||||
Vec3d origin = getOrigin(source);
|
||||
|
||||
source.spawnParticles(getOrigin(source), new Sphere(false, range), 7, p -> {
|
||||
source.spawnParticles(origin, new Sphere(false, range), 7, p -> {
|
||||
source.addParticle(
|
||||
new FollowingParticleEffect(UParticles.HEALTH_DRAIN, source.asEntity(), 0.4F)
|
||||
.withChild(new MagicParticleEffect(getType().getColor())),
|
||||
new FollowingParticleEffect(UParticles.HEALTH_DRAIN, origin, 0.4F)
|
||||
.withChild(ParticleTypes.AMBIENT_ENTITY_EFFECT),
|
||||
p,
|
||||
Vec3d.ZERO
|
||||
);
|
||||
|
|
|
@ -11,12 +11,10 @@ import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
|
|||
import com.minelittlepony.unicopia.entity.*;
|
||||
import com.minelittlepony.unicopia.entity.mob.UEntityAttributes;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
import com.minelittlepony.unicopia.particle.ParticleHandle;
|
||||
import com.minelittlepony.unicopia.particle.SphereParticleEffect;
|
||||
import com.minelittlepony.unicopia.particle.UParticles;
|
||||
import com.minelittlepony.unicopia.particle.ParticleHandle.Attachment;
|
||||
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
|
||||
import com.minelittlepony.unicopia.projectile.ProjectileDelegate;
|
||||
import com.minelittlepony.unicopia.util.shape.Sphere;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
|
@ -48,11 +46,11 @@ public class BubbleSpell extends AbstractSpell implements TimedSpell,
|
|||
.with(Trait.POWER, 1)
|
||||
.build();
|
||||
|
||||
protected final ParticleHandle particlEffect = new ParticleHandle();
|
||||
|
||||
private final Timer timer;
|
||||
|
||||
private int struggles;
|
||||
|
||||
private float prevRadius;
|
||||
private float radius;
|
||||
|
||||
protected BubbleSpell(CustomisedSpellType<?> type) {
|
||||
|
@ -66,6 +64,10 @@ public class BubbleSpell extends AbstractSpell implements TimedSpell,
|
|||
return timer;
|
||||
}
|
||||
|
||||
public float getRadius(float tickDelta) {
|
||||
return MathHelper.lerp(tickDelta, prevRadius, radius);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Caster<?> source) {
|
||||
|
||||
|
@ -95,14 +97,19 @@ public class BubbleSpell extends AbstractSpell implements TimedSpell,
|
|||
public boolean tick(Caster<?> source, Situation situation) {
|
||||
|
||||
if (situation == Situation.PROJECTILE) {
|
||||
|
||||
source.spawnParticles(ParticleTypes.BUBBLE, 2);
|
||||
source.spawnParticles(UParticles.BUBBLE, 2);
|
||||
return true;
|
||||
}
|
||||
|
||||
timer.tick();
|
||||
|
||||
if (timer.getTicksRemaining() <= 0) {
|
||||
boolean done = timer.getTicksRemaining() <= 0;
|
||||
|
||||
source.spawnParticles(source.getOriginVector().add(0, 1, 0), new Sphere(true, radius * (done ? 0.25F : 0.5F)), done ? 13 : 1, pos -> {
|
||||
source.addParticle(done ? ParticleTypes.BUBBLE_POP : UParticles.BUBBLE, pos, Vec3d.ZERO);
|
||||
});
|
||||
|
||||
if (done) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -116,7 +123,7 @@ public class BubbleSpell extends AbstractSpell implements TimedSpell,
|
|||
|
||||
source.asEntity().fallDistance = 0;
|
||||
|
||||
Vec3d origin = source.getOriginVector();
|
||||
prevRadius = radius;
|
||||
|
||||
if (source instanceof Pony pony && pony.sneakingChanged() && pony.asEntity().isSneaking()) {
|
||||
setDirty();
|
||||
|
@ -128,18 +135,11 @@ public class BubbleSpell extends AbstractSpell implements TimedSpell,
|
|||
}
|
||||
}
|
||||
|
||||
particlEffect.update(getUuid(), source, spawner -> {
|
||||
spawner.addParticle(new SphereParticleEffect(UParticles.SPHERE, 0xFFFFFF, 0.3F, 0, new Vec3d(0, radius / 2F, 0)), origin, Vec3d.ZERO);
|
||||
}).ifPresent(p -> {
|
||||
p.setAttribute(Attachment.ATTR_RADIUS, radius);
|
||||
});
|
||||
|
||||
return !isDead();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroyed(Caster<?> source) {
|
||||
particlEffect.destroy();
|
||||
if (source.asEntity() instanceof LivingEntity l) {
|
||||
MODIFIERS.forEach((attribute, modifier) -> {
|
||||
if (l.getAttributes().hasAttribute(attribute)) {
|
||||
|
|
|
@ -10,11 +10,11 @@ import com.minelittlepony.unicopia.ability.magic.spell.Situation;
|
|||
import com.minelittlepony.unicopia.ability.magic.spell.Spell;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
|
||||
import com.minelittlepony.unicopia.entity.Living;
|
||||
import com.minelittlepony.unicopia.entity.damage.UDamageTypes;
|
||||
import com.minelittlepony.unicopia.particle.ParticleHandle.Attachment;
|
||||
import com.minelittlepony.unicopia.particle.FollowingParticleEffect;
|
||||
import com.minelittlepony.unicopia.particle.LightningBoltParticleEffect;
|
||||
import com.minelittlepony.unicopia.particle.ParticleUtils;
|
||||
import com.minelittlepony.unicopia.particle.SphereParticleEffect;
|
||||
import com.minelittlepony.unicopia.particle.UParticles;
|
||||
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
|
||||
import com.minelittlepony.unicopia.projectile.ProjectileDelegate;
|
||||
|
@ -48,7 +48,6 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileDelega
|
|||
|
||||
private static final Vec3d SPHERE_OFFSET = new Vec3d(0, 2, 0);
|
||||
|
||||
private int age = 0;
|
||||
private float accumulatedMass = 0;
|
||||
|
||||
protected DarkVortexSpell(CustomisedSpellType<?> type) {
|
||||
|
@ -80,10 +79,7 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileDelega
|
|||
return true;
|
||||
}
|
||||
|
||||
age++;
|
||||
setDirty();
|
||||
|
||||
if (age % 20 == 0) {
|
||||
if (source.asEntity().age % 20 == 0) {
|
||||
source.asWorld().playSound(null, source.getOrigin(), USounds.AMBIENT_DARK_VORTEX_ADDITIONS, SoundCategory.AMBIENT, 1, 1);
|
||||
}
|
||||
|
||||
|
@ -116,21 +112,20 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileDelega
|
|||
public void generateParticles(Caster<?> source) {
|
||||
super.generateParticles(source);
|
||||
|
||||
float radius = (float)getEventHorizonRadius();
|
||||
|
||||
particlEffect.update(getUuid(), source, spawner -> {
|
||||
spawner.addParticle(new SphereParticleEffect(UParticles.SPHERE, 0x000000, 0.99F, radius, SPHERE_OFFSET), source.getOriginVector(), Vec3d.ZERO);
|
||||
}).ifPresent(p -> {
|
||||
p.setAttribute(Attachment.ATTR_RADIUS, radius);
|
||||
p.setAttribute(Attachment.ATTR_OPACITY, 2F);
|
||||
});
|
||||
particlEffect.update(getUuid(), "_ring", source, spawner -> {
|
||||
spawner.addParticle(new SphereParticleEffect(UParticles.DISK, 0xAAAAAA, 0.4F, radius + 1, SPHERE_OFFSET), getOrigin(source), Vec3d.ZERO);
|
||||
}).ifPresent(p -> {
|
||||
p.setAttribute(Attachment.ATTR_RADIUS, radius * 0F);
|
||||
});
|
||||
|
||||
source.spawnParticles(ParticleTypes.SMOKE, 3);
|
||||
if (getEventHorizonRadius() > 0.3) {
|
||||
double range = getDrawDropOffRange(source);
|
||||
Vec3d origin = getOrigin(source);
|
||||
source.spawnParticles(origin, new Sphere(false, range), 1, p -> {
|
||||
if (!source.asWorld().isAir(BlockPos.ofFloored(p))) {
|
||||
source.addParticle(
|
||||
new FollowingParticleEffect(UParticles.HEALTH_DRAIN, origin, 0.4F)
|
||||
.withChild(ParticleTypes.CAMPFIRE_SIGNAL_SMOKE),
|
||||
p,
|
||||
Vec3d.ZERO
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -162,7 +157,6 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileDelega
|
|||
applyRadialEffect(source, e, e.getPos().distanceTo(origin), radius);
|
||||
});
|
||||
}
|
||||
setDirty();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -180,8 +174,8 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileDelega
|
|||
// 2. max force (at dist 0) is taken from accumulated mass
|
||||
// 3. force reaches 0 at distance of drawDropOffRange
|
||||
|
||||
private double getEventHorizonRadius() {
|
||||
return Math.sqrt(Math.max(0.001, getMass() - 12));
|
||||
public double getEventHorizonRadius() {
|
||||
return Math.sqrt(Math.max(0.001, getMass() / 3F));
|
||||
}
|
||||
|
||||
private double getAttractiveForce(Caster<?> source, Entity target) {
|
||||
|
@ -189,8 +183,7 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileDelega
|
|||
}
|
||||
|
||||
private double getMass() {
|
||||
float pulse = (float)Math.sin(age * 8) / 1F;
|
||||
return 10 + Math.min(15, Math.min(0.5F + pulse, (float)Math.exp(age) / 8F - 90) + accumulatedMass / 10F) + pulse;
|
||||
return Math.min(15, 0.1F + accumulatedMass / 10F);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -202,6 +195,11 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileDelega
|
|||
|
||||
if (distance <= getEventHorizonRadius() + 0.5) {
|
||||
target.setVelocity(target.getVelocity().multiply(distance / (2 * radius)));
|
||||
if (distance < 1) {
|
||||
target.setVelocity(target.getVelocity().multiply(distance));
|
||||
|
||||
}
|
||||
Living.updateVelocity(target);
|
||||
|
||||
@Nullable
|
||||
Entity master = source.getMaster();
|
||||
|
@ -221,13 +219,19 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileDelega
|
|||
|
||||
double massOfTarget = AttractionUtils.getMass(target);
|
||||
|
||||
accumulatedMass += massOfTarget;
|
||||
setDirty();
|
||||
if (!source.isClient() && massOfTarget != 0) {
|
||||
accumulatedMass += massOfTarget;
|
||||
setDirty();
|
||||
}
|
||||
|
||||
target.damage(source.damageOf(UDamageTypes.GAVITY_WELL_RECOIL, source), Integer.MAX_VALUE);
|
||||
if (!(target instanceof PlayerEntity)) {
|
||||
target.discard();
|
||||
source.asWorld().playSound(null, source.getOrigin(), USounds.ENCHANTMENT_CONSUMPTION_CONSUME, SoundCategory.AMBIENT, 2, 0.02F);
|
||||
}
|
||||
if (target.isAlive()) {
|
||||
target.damage(source.asEntity().getDamageSources().outOfWorld(), Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
source.subtractEnergyCost(-massOfTarget * 10);
|
||||
source.asWorld().playSound(null, source.getOrigin(), USounds.AMBIENT_DARK_VORTEX_MOOD, SoundCategory.AMBIENT, 2, 0.02F);
|
||||
|
@ -243,14 +247,12 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileDelega
|
|||
@Override
|
||||
public void toNBT(NbtCompound compound) {
|
||||
super.toNBT(compound);
|
||||
compound.putInt("age", age);
|
||||
compound.putFloat("accumulatedMass", accumulatedMass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromNBT(NbtCompound compound) {
|
||||
super.fromNBT(compound);
|
||||
age = compound.getInt("age");
|
||||
accumulatedMass = compound.getFloat("accumulatedMass");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,8 +6,6 @@ import com.minelittlepony.unicopia.ability.magic.spell.*;
|
|||
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
|
||||
import com.minelittlepony.unicopia.entity.EntityReference;
|
||||
import com.minelittlepony.unicopia.entity.damage.UDamageTypes;
|
||||
import com.minelittlepony.unicopia.entity.mob.CastSpellEntity;
|
||||
import com.minelittlepony.unicopia.particle.ParticleHandle.Attachment;
|
||||
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
|
||||
import com.minelittlepony.unicopia.projectile.ProjectileDelegate;
|
||||
|
||||
|
@ -16,7 +14,7 @@ import net.minecraft.nbt.NbtCompound;
|
|||
import net.minecraft.util.hit.EntityHitResult;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
public class DisplacementSpell extends AbstractSpell implements HomingSpell, PlaceableSpell.PlacementDelegate, ProjectileDelegate.EntityHitListener {
|
||||
public class DisplacementSpell extends AbstractSpell implements HomingSpell, ProjectileDelegate.EntityHitListener {
|
||||
|
||||
private final EntityReference<Entity> target = new EntityReference<>();
|
||||
|
||||
|
@ -67,19 +65,6 @@ public class DisplacementSpell extends AbstractSpell implements HomingSpell, Pla
|
|||
originator.subtractEnergyCost(destinationPos.distanceTo(sourcePos) / 20F);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlaced(Caster<?> source, PlaceableSpell parent, CastSpellEntity entity) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updatePlacement(Caster<?> caster, PlaceableSpell parent) {
|
||||
parent.getParticleEffectAttachment(caster).ifPresent(attachment -> {
|
||||
float r = 3 - (1 - ((ticks + 10) / 20F)) * 3;
|
||||
attachment.setAttribute(Attachment.ATTR_RADIUS, r);
|
||||
});
|
||||
}
|
||||
|
||||
private void teleport(Caster<?> source, Entity entity, Vec3d pos, Vec3d vel) {
|
||||
entity.teleport(pos.x, pos.y, pos.z);
|
||||
entity.setVelocity(vel);
|
||||
|
|
|
@ -14,7 +14,6 @@ import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
|
|||
import com.minelittlepony.unicopia.entity.EntityReference;
|
||||
import com.minelittlepony.unicopia.entity.mob.CastSpellEntity;
|
||||
import com.minelittlepony.unicopia.particle.*;
|
||||
import com.minelittlepony.unicopia.particle.ParticleHandle.Attachment;
|
||||
import com.minelittlepony.unicopia.server.world.Ether;
|
||||
import com.minelittlepony.unicopia.util.shape.*;
|
||||
|
||||
|
@ -177,14 +176,6 @@ public class PortalSpell extends AbstractSpell implements PlaceableSpell.Placeme
|
|||
entity.setPos(targetPos.x, caster.getY() + 1.5, targetPos.z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updatePlacement(Caster<?> source, PlaceableSpell parent) {
|
||||
parent.getParticleEffectAttachment(source).ifPresent(attachment -> {
|
||||
attachment.setAttribute(Attachment.ATTR_RADIUS, 2);
|
||||
attachment.setAttribute(Attachment.ATTR_OPACITY, 0.92F);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroyed(Caster<?> caster) {
|
||||
particleEffect.destroy();
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package com.minelittlepony.unicopia.ability.magic.spell.effect;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import com.minelittlepony.unicopia.Affinity;
|
||||
import com.minelittlepony.unicopia.USounds;
|
||||
import com.minelittlepony.unicopia.Unicopia;
|
||||
|
@ -10,11 +12,9 @@ import com.minelittlepony.unicopia.ability.magic.spell.Spell;
|
|||
import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
import com.minelittlepony.unicopia.particle.LightningBoltParticleEffect;
|
||||
import com.minelittlepony.unicopia.particle.MagicParticleEffect;
|
||||
import com.minelittlepony.unicopia.particle.ParticleHandle;
|
||||
import com.minelittlepony.unicopia.particle.SphereParticleEffect;
|
||||
import com.minelittlepony.unicopia.particle.UParticles;
|
||||
import com.minelittlepony.unicopia.particle.ParticleHandle.Attachment;
|
||||
import com.minelittlepony.unicopia.particle.ParticleUtils;
|
||||
import com.minelittlepony.unicopia.projectile.ProjectileUtil;
|
||||
import com.minelittlepony.unicopia.util.shape.Sphere;
|
||||
|
||||
|
@ -30,6 +30,7 @@ import net.minecraft.entity.passive.PassiveEntity;
|
|||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.vehicle.AbstractMinecartEntity;
|
||||
import net.minecraft.entity.vehicle.BoatEntity;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
public class ShieldSpell extends AbstractSpell {
|
||||
|
@ -40,10 +41,14 @@ public class ShieldSpell extends AbstractSpell {
|
|||
.with(Trait.AIR, 9)
|
||||
.build();
|
||||
|
||||
protected final ParticleHandle particlEffect = new ParticleHandle();
|
||||
|
||||
private final TargetSelecter targetSelecter = new TargetSelecter(this);
|
||||
|
||||
private float prevRadius;
|
||||
private float radius;
|
||||
|
||||
private float rangeMultiplier;
|
||||
private float targetRangeMultiplier;
|
||||
|
||||
protected ShieldSpell(CustomisedSpellType<?> type) {
|
||||
super(type);
|
||||
}
|
||||
|
@ -53,33 +58,27 @@ public class ShieldSpell extends AbstractSpell {
|
|||
return method == CastingMethod.STAFF || getTraits().get(Trait.GENEROSITY) > 0 ? toPlaceable() : this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroyed(Caster<?> caster) {
|
||||
particlEffect.destroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Affinity getAffinity() {
|
||||
return getTraits().get(Trait.DARKNESS) > 0 ? Affinity.BAD : Affinity.GOOD;
|
||||
}
|
||||
|
||||
protected void generateParticles(Caster<?> source) {
|
||||
float radius = (float)getDrawDropOffRange(source);
|
||||
Vec3d origin = getOrigin(source);
|
||||
|
||||
source.spawnParticles(origin, new Sphere(true, radius), (int)(radius * 6), pos -> {
|
||||
source.addParticle(new MagicParticleEffect(getType().getColor()), pos, Vec3d.ZERO);
|
||||
});
|
||||
|
||||
particlEffect.update(getUuid(), source, spawner -> {
|
||||
spawner.addParticle(new SphereParticleEffect(UParticles.SPHERE, getType().getColor(), 0.3F, radius), origin, Vec3d.ZERO);
|
||||
}).ifPresent(p -> {
|
||||
p.setAttribute(Attachment.ATTR_RADIUS, radius);
|
||||
if (source.asWorld().random.nextInt(10) == 0 && source.asWorld().random.nextFloat() < source.getCorruption().getScaled(1)) {
|
||||
ParticleUtils.spawnParticle(source.asWorld(), new LightningBoltParticleEffect(true, 3, 2, 0.1F, Optional.empty()), pos, Vec3d.ZERO);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean tick(Caster<?> source, Situation situation) {
|
||||
prevRadius = radius;
|
||||
radius = (float)getDrawDropOffRange(source);
|
||||
|
||||
if (source.isClient()) {
|
||||
generateParticles(source);
|
||||
|
@ -108,20 +107,32 @@ public class ShieldSpell extends AbstractSpell {
|
|||
|
||||
cost *= costMultiplier / ((1 + source.getLevel().get()) * 3F);
|
||||
cost /= knowledge;
|
||||
cost += getDrawDropOffRange(source) / 10F;
|
||||
cost += radius / 10F;
|
||||
|
||||
if (!source.subtractEnergyCost(cost)) {
|
||||
setDead();
|
||||
}
|
||||
}
|
||||
|
||||
public float getRadius(float tickDelta) {
|
||||
return MathHelper.lerp(tickDelta, prevRadius, radius);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the maximum radius of the shield. aka The area of effect.
|
||||
*/
|
||||
public double getDrawDropOffRange(Caster<?> source) {
|
||||
float multiplier = source instanceof Pony pony && pony.asEntity().isSneaking() ? 1 : 2;
|
||||
targetRangeMultiplier = source instanceof Pony pony && pony.asEntity().isSneaking() ? 1 : 2;
|
||||
if (rangeMultiplier < targetRangeMultiplier - 0.1F) {
|
||||
rangeMultiplier += 0.1F;
|
||||
} else if (rangeMultiplier > targetRangeMultiplier + 0.1) {
|
||||
rangeMultiplier -= 0.1F;
|
||||
} else {
|
||||
rangeMultiplier = targetRangeMultiplier;
|
||||
}
|
||||
|
||||
float min = (source instanceof Pony ? 4 : 6) + getTraits().get(Trait.POWER);
|
||||
double range = (min + (source.getLevel().getScaled(source instanceof Pony ? 4 : 40) * (source instanceof Pony ? 2 : 10))) / multiplier;
|
||||
double range = (min + (source.getLevel().getScaled(source instanceof Pony ? 4 : 40) * (source instanceof Pony ? 2 : 10))) / rangeMultiplier;
|
||||
|
||||
return range;
|
||||
}
|
||||
|
@ -150,7 +161,7 @@ public class ShieldSpell extends AbstractSpell {
|
|||
}
|
||||
|
||||
protected long applyEntities(Caster<?> source) {
|
||||
double radius = getDrawDropOffRange(source);
|
||||
double radius = this.radius;
|
||||
|
||||
Vec3d origin = getOrigin(source);
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@ import java.util.stream.Stream;
|
|||
import com.minelittlepony.unicopia.EquinePredicates;
|
||||
import com.minelittlepony.unicopia.ability.magic.Affine;
|
||||
import com.minelittlepony.unicopia.ability.magic.Caster;
|
||||
import com.minelittlepony.unicopia.ability.magic.SpellPredicate;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.Spell;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
import com.minelittlepony.unicopia.item.FriendshipBraceletItem;
|
||||
|
@ -29,7 +28,7 @@ public class TargetSelecter {
|
|||
public Stream<Entity> getEntities(Caster<?> source, double radius, BiPredicate<Caster<?>, Entity> filter) {
|
||||
targets.values().removeIf(Target::tick);
|
||||
return source.findAllEntitiesInRange(radius)
|
||||
.filter(entity -> entity.isAlive() && !entity.isRemoved() && notOwnerOrFriend(spell, source, entity) && !SpellPredicate.IS_SHIELD_LIKE.isOn(entity))
|
||||
.filter(entity -> entity.isAlive() && !entity.isRemoved() && notOwnerOrFriend(spell, source, entity))
|
||||
.filter(EquinePredicates.EXCEPT_MAGIC_IMMUNE)
|
||||
.filter(e -> filter.test(source, e))
|
||||
.map(i -> {
|
||||
|
@ -57,6 +56,11 @@ public class TargetSelecter {
|
|||
public static <T extends Entity> boolean isOwnerOrFriend(Affine affine, Caster<?> source, Entity target) {
|
||||
Entity owner = source.getMaster();
|
||||
|
||||
var equine = Pony.of(target);
|
||||
if (equine.isPresent() && !affine.isFriendlyTogether(equine.get())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (affine.isEnemy(source)) {
|
||||
return FriendshipBraceletItem.isComrade(source, target);
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import com.minelittlepony.unicopia.block.cloud.CloudChestBlock;
|
|||
import com.minelittlepony.unicopia.client.particle.ChangelingMagicParticle;
|
||||
import com.minelittlepony.unicopia.client.particle.CloudsEscapingParticle;
|
||||
import com.minelittlepony.unicopia.client.particle.DiskParticle;
|
||||
import com.minelittlepony.unicopia.client.particle.FloatingBubbleParticle;
|
||||
import com.minelittlepony.unicopia.client.particle.GroundPoundParticle;
|
||||
import com.minelittlepony.unicopia.client.particle.HealthDrainParticle;
|
||||
import com.minelittlepony.unicopia.client.particle.LightningBoltParticle;
|
||||
|
@ -65,6 +66,7 @@ public interface URenderers {
|
|||
static void bootstrap() {
|
||||
ParticleFactoryRegistry.getInstance().register(UParticles.UNICORN_MAGIC, createFactory(MagicParticle::new));
|
||||
ParticleFactoryRegistry.getInstance().register(UParticles.CHANGELING_MAGIC, createFactory(ChangelingMagicParticle::new));
|
||||
ParticleFactoryRegistry.getInstance().register(UParticles.BUBBLE, createFactory(FloatingBubbleParticle::new));
|
||||
ParticleFactoryRegistry.getInstance().register(UParticles.RAIN_DROPS, createFactory(RaindropsParticle::new));
|
||||
ParticleFactoryRegistry.getInstance().register(UParticles.HEALTH_DRAIN, createFactory(HealthDrainParticle::create));
|
||||
ParticleFactoryRegistry.getInstance().register(UParticles.RAINBOOM_RING, RainboomParticle::new);
|
||||
|
|
|
@ -7,6 +7,8 @@ import com.minelittlepony.unicopia.*;
|
|||
import com.minelittlepony.unicopia.ability.*;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.effect.CustomisedSpellType;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType;
|
||||
import com.minelittlepony.unicopia.client.render.RenderLayers;
|
||||
import com.minelittlepony.unicopia.client.render.spell.DarkVortexSpellRenderer;
|
||||
import com.minelittlepony.unicopia.client.sound.*;
|
||||
import com.minelittlepony.unicopia.entity.ItemTracker;
|
||||
import com.minelittlepony.unicopia.entity.effect.EffectUtils;
|
||||
|
@ -193,6 +195,19 @@ public class UHud {
|
|||
|
||||
protected void renderViewEffects(Pony pony, DrawContext context, int scaledWidth, int scaledHeight, float tickDelta) {
|
||||
|
||||
float vortexDistortion = DarkVortexSpellRenderer.getCameraDistortion();
|
||||
|
||||
if (vortexDistortion > 20) {
|
||||
context.fill(RenderLayers.getEndPortal(), 0, 0, scaledWidth, scaledHeight, 0);
|
||||
context.getMatrices().push();
|
||||
context.getMatrices().translate(scaledWidth / 2, scaledHeight / 2, 0);
|
||||
DrawableUtil.drawArc(context.getMatrices(), 0, 20, 0, MathHelper.TAU, 0x000000FF, false);
|
||||
context.getMatrices().pop();
|
||||
return;
|
||||
} else if (vortexDistortion > 0) {
|
||||
context.fill(0, 0, scaledWidth, scaledHeight, (int)((vortexDistortion / 20F) * 255) << 24);
|
||||
}
|
||||
|
||||
boolean hasEffect = client.player.hasStatusEffect(UEffects.SUN_BLINDNESS);
|
||||
|
||||
ItemStack glasses = GlassesItem.getForEntity(client.player);
|
||||
|
|
|
@ -30,7 +30,7 @@ public class CloudsEscapingParticle extends GroundPoundParticle {
|
|||
);
|
||||
|
||||
double columnHeight = 1 + age / 30;
|
||||
new Sphere(true, columnHeight, 1, 1, 1)
|
||||
new Sphere(true, columnHeight)
|
||||
.translate(center)
|
||||
.randomPoints(random)
|
||||
.forEach(point -> {
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
package com.minelittlepony.unicopia.client.particle;
|
||||
|
||||
import net.minecraft.client.particle.ParticleTextureSheet;
|
||||
import net.minecraft.client.particle.SpriteBillboardParticle;
|
||||
import net.minecraft.client.particle.SpriteProvider;
|
||||
import net.minecraft.client.world.ClientWorld;
|
||||
import net.minecraft.particle.ParticleEffect;
|
||||
import net.minecraft.particle.ParticleTypes;
|
||||
|
||||
public class FloatingBubbleParticle extends SpriteBillboardParticle {
|
||||
public FloatingBubbleParticle(ParticleEffect effect, SpriteProvider provider, ClientWorld clientWorld, double x, double y, double z, double dX, double dY, double dZ) {
|
||||
super(clientWorld, x, y, z, dX, dY, dZ);
|
||||
setSprite(provider);
|
||||
scale((float)clientWorld.random.nextTriangular(1F, 0.5F));
|
||||
this.velocityX *= -0.1F;
|
||||
this.velocityY *= -0.1F;
|
||||
this.velocityZ *= -0.1F;
|
||||
this.maxAge *= 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParticleTextureSheet getType() {
|
||||
return ParticleTextureSheet.PARTICLE_SHEET_OPAQUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markDead() {
|
||||
super.markDead();
|
||||
world.addParticle(ParticleTypes.BUBBLE_POP, x, y, z, 0, 0, 0);
|
||||
}
|
||||
}
|
|
@ -22,7 +22,6 @@ public abstract class OrientedBillboardParticle extends AbstractBillboardParticl
|
|||
|
||||
fixed = effect.fixed();
|
||||
if (fixed) {
|
||||
// Was hamiltonianProduct (CHECK THIS!!)
|
||||
rotation.mul(RotationAxis.POSITIVE_Y.rotationDegrees(effect.pitch()));
|
||||
rotation.mul(RotationAxis.POSITIVE_X.rotationDegrees(180 - effect.yaw()));
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import net.minecraft.entity.Entity;
|
|||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.*;
|
||||
|
||||
@Deprecated
|
||||
public class RunesParticle extends OrientedBillboardParticle implements Attachment {
|
||||
|
||||
private static final Identifier[] TEXTURES = new Identifier[] {
|
||||
|
|
|
@ -6,6 +6,7 @@ import org.jetbrains.annotations.Nullable;
|
|||
|
||||
import com.minelittlepony.unicopia.ability.magic.Caster;
|
||||
import com.minelittlepony.unicopia.client.FirstPersonRendererOverrides.ArmRenderer;
|
||||
import com.minelittlepony.unicopia.client.minelittlepony.MineLPDelegate;
|
||||
import com.minelittlepony.unicopia.client.render.spell.SpellEffectsRenderDispatcher;
|
||||
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
|
@ -13,14 +14,14 @@ import net.minecraft.client.model.ModelPart;
|
|||
import net.minecraft.client.render.VertexConsumerProvider;
|
||||
import net.minecraft.client.render.entity.feature.FeatureRenderer;
|
||||
import net.minecraft.client.render.entity.feature.FeatureRendererContext;
|
||||
import net.minecraft.client.render.entity.model.BipedEntityModel;
|
||||
import net.minecraft.client.render.entity.model.EntityModel;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.util.Arm;
|
||||
|
||||
public class AccessoryFeatureRenderer<
|
||||
T extends LivingEntity,
|
||||
M extends BipedEntityModel<T>> extends FeatureRenderer<T, M> {
|
||||
M extends EntityModel<T>> extends FeatureRenderer<T, M> {
|
||||
|
||||
private static final List<FeatureFactory<?>> REGISTRY = new ArrayList<>();
|
||||
|
||||
|
@ -40,6 +41,10 @@ public class AccessoryFeatureRenderer<
|
|||
|
||||
@Override
|
||||
public void render(MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, T entity, float limbAngle, float limbDistance, float tickDelta, float animationProgress, float headYaw, float headPitch) {
|
||||
if (MineLPDelegate.getInstance().getRace(entity).isEquine()) {
|
||||
return;
|
||||
}
|
||||
|
||||
features.forEach(feature -> feature.render(matrices, vertexConsumers, light, entity, limbAngle, limbDistance, tickDelta, animationProgress, headYaw, headPitch));
|
||||
|
||||
Caster.of(entity).ifPresent(caster -> {
|
||||
|
@ -60,7 +65,7 @@ public class AccessoryFeatureRenderer<
|
|||
}
|
||||
|
||||
public interface FeatureFactory<T extends LivingEntity> {
|
||||
Feature<T> create(FeatureRendererContext<T, ? extends BipedEntityModel<T>> context);
|
||||
Feature<T> create(FeatureRendererContext<T, ? extends EntityModel<T>> context);
|
||||
}
|
||||
|
||||
public interface Feature<T extends LivingEntity> {
|
||||
|
@ -75,11 +80,11 @@ public class AccessoryFeatureRenderer<
|
|||
|
||||
public interface FeatureRoot<
|
||||
T extends LivingEntity,
|
||||
M extends BipedEntityModel<T>> {
|
||||
M extends EntityModel<T>> {
|
||||
AccessoryFeatureRenderer<T, M> getAccessories();
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nullable
|
||||
static <T extends LivingEntity, M extends BipedEntityModel<T>> FeatureRoot<T, M> of(T entity) {
|
||||
static <T extends LivingEntity, M extends EntityModel<T>> FeatureRoot<T, M> of(T entity) {
|
||||
var renderer = MinecraftClient.getInstance().getEntityRenderDispatcher().getRenderer(entity);
|
||||
if (renderer instanceof FeatureRoot) {
|
||||
return (FeatureRoot<T, M>)renderer;
|
||||
|
|
|
@ -39,6 +39,15 @@ public final class RenderLayers extends RenderLayer {
|
|||
.target(TRANSLUCENT_TARGET)
|
||||
.build(false));
|
||||
|
||||
private static final RenderLayer MAGIC_SHIELD = of("magic_shield", VertexFormats.POSITION_COLOR_TEXTURE_OVERLAY_LIGHT_NORMAL,
|
||||
VertexFormat.DrawMode.QUADS, 256, true, true, MultiPhaseParameters.builder()
|
||||
.program(COLOR_PROGRAM)
|
||||
.transparency(TRANSLUCENT_TRANSPARENCY)
|
||||
.target(TRANSLUCENT_TARGET)
|
||||
.cull(DISABLE_CULLING)
|
||||
.writeMaskState(COLOR_MASK)
|
||||
.build(false));
|
||||
|
||||
private static final Function<Integer, RenderLayer> MAGIC_COLORIN_FUNC = Util.memoize(color -> {
|
||||
return of("magic_colored_" + color,
|
||||
VertexFormats.POSITION_COLOR_TEXTURE_OVERLAY_LIGHT_NORMAL,
|
||||
|
@ -75,6 +84,10 @@ public final class RenderLayers extends RenderLayer {
|
|||
return MAGIC_NO_COLOR;
|
||||
}
|
||||
|
||||
public static RenderLayer getMagicShield() {
|
||||
return MAGIC_SHIELD;
|
||||
}
|
||||
|
||||
public static RenderLayer getMagicColored() {
|
||||
return MAGIC_COLORED;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package com.minelittlepony.unicopia.client.render;
|
||||
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Vector3f;
|
||||
import org.joml.Vector4f;
|
||||
|
||||
|
@ -11,7 +10,7 @@ import net.minecraft.client.render.VertexFormats;
|
|||
import net.minecraft.client.util.math.MatrixStack;
|
||||
|
||||
public class RenderUtil {
|
||||
private static final Vector4f TEMP_VECTOR = new Vector4f();
|
||||
public static final Vector4f TEMP_VECTOR = new Vector4f();
|
||||
public static final Vertex[] UNIT_FACE = new Vertex[] {
|
||||
new Vertex(new Vector3f(0, 0, 0), 1, 1),
|
||||
new Vertex(new Vector3f(0, 1, 0), 1, 0),
|
||||
|
@ -21,21 +20,18 @@ public class RenderUtil {
|
|||
|
||||
public static void renderFace(MatrixStack matrices, Tessellator te, BufferBuilder buffer, float r, float g, float b, float a, int light) {
|
||||
buffer.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE_COLOR_LIGHT);
|
||||
|
||||
Vertex[] UNIT_FACE = new Vertex[] {
|
||||
new Vertex(new Vector3f(0, 0, 0), 1, 1),
|
||||
new Vertex(new Vector3f(0, 1, 0), 1, 0),
|
||||
new Vertex(new Vector3f(1, 1, 0), 0, 0),
|
||||
new Vertex(new Vector3f(1, 0, 0), 0, 1)
|
||||
};
|
||||
|
||||
Matrix4f transformation = matrices.peek().getPositionMatrix();
|
||||
for (Vertex vertex : UNIT_FACE) {
|
||||
transformation.transform(TEMP_VECTOR.set(vertex.position(), 1));
|
||||
buffer.vertex(TEMP_VECTOR.x, TEMP_VECTOR.y, TEMP_VECTOR.z).texture(vertex.u(), vertex.v()).color(r, g, b, a).light(light).next();
|
||||
Vector4f position = vertex.position(matrices);
|
||||
buffer.vertex(position.x, position.y, position.z).texture(vertex.u(), vertex.v()).color(r, g, b, a).light(light).next();
|
||||
}
|
||||
te.draw();
|
||||
}
|
||||
|
||||
record Vertex(Vector3f position, float u, float v) {}
|
||||
public record Vertex(Vector3f position, float u, float v) {
|
||||
|
||||
public Vector4f position(MatrixStack matrices) {
|
||||
matrices.peek().getPositionMatrix().transform(TEMP_VECTOR.set(position, 1));
|
||||
return TEMP_VECTOR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,8 +11,6 @@ import net.minecraft.screen.PlayerScreenHandler;
|
|||
import net.minecraft.util.Identifier;
|
||||
|
||||
public class CastSpellEntityRenderer extends EntityRenderer<CastSpellEntity> {
|
||||
private final SpellEffectsRenderDispatcher spellRenderDispatcher = new SpellEffectsRenderDispatcher();
|
||||
|
||||
public CastSpellEntityRenderer(EntityRendererFactory.Context ctx) {
|
||||
super(ctx);
|
||||
}
|
||||
|
@ -24,7 +22,7 @@ public class CastSpellEntityRenderer extends EntityRenderer<CastSpellEntity> {
|
|||
|
||||
@Override
|
||||
public void render(CastSpellEntity entity, float yaw, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light) {
|
||||
spellRenderDispatcher.render(matrices, vertexConsumers, light, entity, 0, 0, tickDelta, getAnimationProgress(entity, tickDelta), yaw, 0);
|
||||
SpellEffectsRenderDispatcher.INSTANCE.render(matrices, vertexConsumers, light, entity, 0, 0, tickDelta, getAnimationProgress(entity, tickDelta), yaw, 0);
|
||||
}
|
||||
|
||||
protected float getAnimationProgress(CastSpellEntity entity, float tickDelta) {
|
||||
|
|
|
@ -3,38 +3,37 @@ package com.minelittlepony.unicopia.client.render.model;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Vector3f;
|
||||
import org.joml.Vector4f;
|
||||
|
||||
import com.minelittlepony.unicopia.client.render.RenderUtil;
|
||||
|
||||
import net.minecraft.client.render.VertexConsumer;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
|
||||
public class BakedModel {
|
||||
private static final Vector4f drawVert = new Vector4f();
|
||||
|
||||
protected final List<Vertex> vertices = new ArrayList<>();
|
||||
protected final List<RenderUtil.Vertex> vertices = new ArrayList<>();
|
||||
|
||||
protected void addVertex(Vector4f vertex) {
|
||||
addVertex(vertex.x, vertex.y, vertex.z, 0, 0);
|
||||
}
|
||||
|
||||
protected void addVertex(float x, float y, float z, float u, float v) {
|
||||
vertices.add(new Vertex(x, y, z, u, v));
|
||||
vertices.add(new RenderUtil.Vertex(new Vector3f(x, y, z), u, v));
|
||||
}
|
||||
|
||||
public final void render(MatrixStack matrices, VertexConsumer vertexWriter, int light, int overlay, float scale, float r, float g, float b, float a) {
|
||||
public final void render(MatrixStack matrices, VertexConsumer buffer, int light, int overlay, float scale, float r, float g, float b, float a) {
|
||||
scale = Math.abs(scale);
|
||||
if (scale < 0.001F) {
|
||||
return;
|
||||
}
|
||||
|
||||
Matrix4f model = matrices.peek().getPositionMatrix();
|
||||
for (Vertex vertex : vertices) {
|
||||
drawVert.set(vertex.x() * scale, vertex.y() * scale, vertex.z() * scale, 1);
|
||||
drawVert.mul(model);
|
||||
vertexWriter.vertex(drawVert.x, drawVert.y, drawVert.z, r, g, b, a, vertex.u(), vertex.v(), overlay, light, 0, 0, 0);
|
||||
matrices.push();
|
||||
matrices.scale(scale, scale, scale);
|
||||
for (RenderUtil.Vertex vertex : vertices) {
|
||||
Vector4f pos = vertex.position(matrices);
|
||||
buffer.vertex(pos.x, pos.y, pos.z, r, g, b, a, vertex.u(), vertex.v(), overlay, light, 0, 0, 0);
|
||||
}
|
||||
matrices.pop();
|
||||
}
|
||||
|
||||
record Vertex(float x, float y, float z, float u, float v) {}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
package com.minelittlepony.unicopia.client.render.model;
|
||||
|
||||
public class PlaneModel extends BakedModel {
|
||||
public static final PlaneModel INSTANCE = new PlaneModel();
|
||||
|
||||
private PlaneModel() {
|
||||
addVertex(-1, -1, 0, 0, 0);
|
||||
addVertex(-1, 1, 0, 1, 0);
|
||||
addVertex( 1, 1, 0, 1, 1);
|
||||
addVertex( 1, -1, 0, 0, 1);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package com.minelittlepony.unicopia.client.render.spell;
|
||||
|
||||
import com.minelittlepony.unicopia.ability.magic.Caster;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.effect.BubbleSpell;
|
||||
import com.minelittlepony.unicopia.client.gui.DrawableUtil;
|
||||
import com.minelittlepony.unicopia.client.render.RenderLayers;
|
||||
import com.minelittlepony.unicopia.client.render.model.SphereModel;
|
||||
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.render.VertexConsumer;
|
||||
import net.minecraft.client.render.VertexConsumerProvider;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.util.math.RotationAxis;
|
||||
|
||||
public class BubbleSpellRenderer implements SpellRenderer<BubbleSpell> {
|
||||
@Override
|
||||
public void render(MatrixStack matrices, VertexConsumerProvider vertices, BubbleSpell spell, Caster<?> caster, int light, float limbAngle, float limbDistance, float tickDelta, float animationProgress, float headYaw, float headPitch) {
|
||||
matrices.push();
|
||||
double height = caster.asEntity().getEyeY() - caster.getOriginVector().y;
|
||||
matrices.translate(0, height * 0.5F, 0);
|
||||
|
||||
float radius = spell.getRadius(tickDelta) * 0.7F;
|
||||
|
||||
VertexConsumer buffer = vertices.getBuffer(RenderLayers.getMagicNoColor());
|
||||
|
||||
Entity cameraEntity = MinecraftClient.getInstance().getCameraEntity();
|
||||
|
||||
matrices.push();
|
||||
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(-45));
|
||||
matrices.multiply(RotationAxis.NEGATIVE_X.rotationDegrees(45 + cameraEntity.getYaw(tickDelta)));
|
||||
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(-cameraEntity.getPitch(tickDelta)));
|
||||
|
||||
new SphereModel(40, 40, DrawableUtil.PI * 0.25F).render(matrices, buffer, light, 0, radius - 0.1F, 0.9F, 0.9F, 1, 0.3F);
|
||||
matrices.pop();
|
||||
|
||||
SphereModel.SPHERE.render(matrices, buffer, light, 0, radius, 0.9F, 0.9F, 1, 0.25F);
|
||||
|
||||
matrices.pop();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
package com.minelittlepony.unicopia.client.render.spell;
|
||||
|
||||
import com.minelittlepony.unicopia.Unicopia;
|
||||
import com.minelittlepony.unicopia.ability.magic.Caster;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.effect.DarkVortexSpell;
|
||||
import com.minelittlepony.unicopia.client.render.RenderLayers;
|
||||
import com.minelittlepony.unicopia.client.render.model.PlaneModel;
|
||||
import com.minelittlepony.unicopia.client.render.model.SphereModel;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.render.RenderLayer;
|
||||
import net.minecraft.client.render.VertexConsumer;
|
||||
import net.minecraft.client.render.VertexConsumerProvider;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.RotationAxis;
|
||||
|
||||
public class DarkVortexSpellRenderer implements SpellRenderer<DarkVortexSpell> {
|
||||
|
||||
private static final Identifier ACCRETION_DISK_TEXTURE = Unicopia.id("textures/spells/dark_vortex/accretion_disk.png");
|
||||
|
||||
private static float cameraDistortion;
|
||||
|
||||
public static float getCameraDistortion() {
|
||||
cameraDistortion *= 0.9F;
|
||||
cameraDistortion = MathHelper.clamp(cameraDistortion, 0, 80);
|
||||
return cameraDistortion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(MatrixStack matrices, VertexConsumerProvider vertices, DarkVortexSpell spell, Caster<?> caster, int light, float limbAngle, float limbDistance, float tickDelta, float animationProgress, float headYaw, float headPitch) {
|
||||
|
||||
|
||||
Entity cameraEntity = MinecraftClient.getInstance().getCameraEntity();
|
||||
|
||||
float radius = (float)spell.getEventHorizonRadius();
|
||||
float absDistance = (float)cameraEntity.getEyePos().distanceTo(caster.getOriginVector().add(0, 2, 0));
|
||||
|
||||
matrices.push();
|
||||
matrices.translate(0, 2 + radius, 0);
|
||||
|
||||
SphereModel.SPHERE.render(matrices, vertices.getBuffer(RenderLayers.getSolid()), light, 1, Math.min(radius * 0.6F, absDistance * 0.1F), 0, 0, 0, 1);
|
||||
|
||||
matrices.push();
|
||||
|
||||
|
||||
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(90));
|
||||
matrices.multiply(RotationAxis.NEGATIVE_X.rotationDegrees(90 + cameraEntity.getYaw(tickDelta)));
|
||||
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(-cameraEntity.getPitch(tickDelta)));
|
||||
|
||||
matrices.scale(0.7F, 1, 1);
|
||||
|
||||
|
||||
float distance = 1F / MathHelper.clamp((absDistance / (radius * 4)), 0.0000001F, 1);
|
||||
distance *= distance;
|
||||
if (absDistance < radius * 4) {
|
||||
cameraDistortion += distance;
|
||||
}
|
||||
|
||||
matrices.scale(distance, distance, distance);
|
||||
|
||||
if (absDistance > radius) {
|
||||
matrices.push();
|
||||
matrices.translate(0, -0.1F, 0);
|
||||
for (int i = 0; i < 10; i++) {
|
||||
matrices.scale(1, 1, 0.796F);
|
||||
float brightness = i / 10F;
|
||||
SphereModel.DISK.render(matrices, vertices.getBuffer(RenderLayers.getMagicNoColor()), light, 1, radius * (1 + (0.25F * i)) * 0.7F, brightness, brightness, brightness, 0.2F);
|
||||
}
|
||||
matrices.pop();
|
||||
}
|
||||
|
||||
SphereModel.DISK.render(matrices, vertices.getBuffer(RenderLayers.getEndPortal()), light, 1, radius * 0.5F, 1, 0.5F, 0, 1);
|
||||
|
||||
if (radius > 0.3F && absDistance > radius) {
|
||||
radius *= 3 + radius;
|
||||
|
||||
matrices.scale(radius, radius, radius);
|
||||
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(90));
|
||||
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(animationProgress * 168));
|
||||
|
||||
VertexConsumer buffer = vertices.getBuffer(RenderLayer.getEntityTranslucent(ACCRETION_DISK_TEXTURE));
|
||||
|
||||
PlaneModel.INSTANCE.render(matrices, buffer, light, 0, 1, 1, 1, 1, 1);
|
||||
|
||||
matrices.push();
|
||||
matrices.scale(0.5F, 0.5F, 0.5F);
|
||||
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(33));
|
||||
|
||||
PlaneModel.INSTANCE.render(matrices, buffer, light, 0, 1, 1, 1, 1, 1);
|
||||
matrices.pop();
|
||||
|
||||
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(45));
|
||||
PlaneModel.INSTANCE.render(matrices, buffer, light, 0, 1, 1, 1, 1, 1);
|
||||
}
|
||||
matrices.pop();
|
||||
matrices.pop();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
package com.minelittlepony.unicopia.client.render.spell;
|
||||
|
||||
import com.minelittlepony.common.util.Color;
|
||||
import com.minelittlepony.unicopia.Unicopia;
|
||||
import com.minelittlepony.unicopia.ability.magic.Caster;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.PlaceableSpell;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.Spell;
|
||||
import com.minelittlepony.unicopia.client.render.model.PlaneModel;
|
||||
import com.minelittlepony.unicopia.entity.mob.CastSpellEntity;
|
||||
|
||||
import net.minecraft.client.render.RenderLayer;
|
||||
import net.minecraft.client.render.VertexConsumer;
|
||||
import net.minecraft.client.render.VertexConsumerProvider;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.RotationAxis;
|
||||
|
||||
public class PlacedSpellRenderer implements SpellRenderer<PlaceableSpell> {
|
||||
private static final Identifier[] TEXTURES = new Identifier[] {
|
||||
Unicopia.id("textures/particles/runes_0.png"),
|
||||
Unicopia.id("textures/particles/runes_1.png"),
|
||||
Unicopia.id("textures/particles/runes_2.png"),
|
||||
Unicopia.id("textures/particles/runes_3.png"),
|
||||
Unicopia.id("textures/particles/runes_4.png"),
|
||||
Unicopia.id("textures/particles/runes_5.png")
|
||||
};
|
||||
|
||||
@Override
|
||||
public void render(MatrixStack matrices, VertexConsumerProvider vertices, PlaceableSpell spell, Caster<?> caster, int light, float limbAngle, float limbDistance, float tickDelta, float animationProgress, float headYaw, float headPitch) {
|
||||
|
||||
if (!(caster.asEntity() instanceof CastSpellEntity)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (Spell delegate : spell.getDelegates()) {
|
||||
|
||||
matrices.push();
|
||||
matrices.translate(0, 0.001, 0);
|
||||
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(spell.pitch));
|
||||
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(90 - spell.yaw));
|
||||
float scale = (spell.getAge(tickDelta) / 25F) * 3;
|
||||
matrices.scale(scale, scale, scale);
|
||||
|
||||
float angle = (animationProgress / 9F) % 360;
|
||||
|
||||
int color = delegate.getType().getColor();
|
||||
|
||||
float red = Color.r(color);
|
||||
float green = Color.g(color);
|
||||
float blue = Color.b(color);
|
||||
|
||||
for (int i = 0; i < TEXTURES.length; i++) {
|
||||
VertexConsumer buffer = vertices.getBuffer(RenderLayer.getEntityTranslucent(TEXTURES[i]));
|
||||
|
||||
for (int dim = 0; dim < 3; dim++) {
|
||||
float ringSpeed = (i % 2 == 0 ? i : -1) * i;
|
||||
|
||||
matrices.push();
|
||||
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(angle * ringSpeed));
|
||||
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(angle * ringSpeed * dim));
|
||||
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(angle * ringSpeed * dim));
|
||||
PlaneModel.INSTANCE.render(matrices, buffer, light, 0, 1, red, green, blue, scale / ((float)(dim * 3) + 1));
|
||||
matrices.pop();
|
||||
}
|
||||
}
|
||||
|
||||
matrices.pop();
|
||||
|
||||
SpellEffectsRenderDispatcher.INSTANCE.render(matrices, vertices, delegate, caster, light, limbAngle, limbDistance, tickDelta, animationProgress, headYaw, headPitch);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package com.minelittlepony.unicopia.client.render.spell;
|
||||
|
||||
import com.minelittlepony.common.util.Color;
|
||||
import com.minelittlepony.unicopia.ability.magic.Caster;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.effect.ShieldSpell;
|
||||
import com.minelittlepony.unicopia.client.render.RenderLayers;
|
||||
import com.minelittlepony.unicopia.client.render.model.SphereModel;
|
||||
import com.minelittlepony.unicopia.util.ColorHelper;
|
||||
|
||||
import net.minecraft.client.render.VertexConsumer;
|
||||
import net.minecraft.client.render.VertexConsumerProvider;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
|
||||
public class ShieldSpellRenderer implements SpellRenderer<ShieldSpell> {
|
||||
@Override
|
||||
public void render(MatrixStack matrices, VertexConsumerProvider vertices, ShieldSpell spell, Caster<?> caster, int light, float limbAngle, float limbDistance, float tickDelta, float animationProgress, float headYaw, float headPitch) {
|
||||
matrices.push();
|
||||
double height = caster.asEntity().getEyeY() - caster.getOriginVector().y;
|
||||
matrices.translate(0, height, 0);
|
||||
|
||||
int color = ColorHelper.lerp(caster.getCorruption().getScaled(1) * (tickDelta / (1 + caster.asWorld().random.nextFloat())), spell.getType().getColor(), 0xFF000);
|
||||
float[] colors = ColorHelper.changeSaturation(Color.r(color), Color.g(color), Color.b(color), 4);
|
||||
float radius = 0.35F + spell.getRadius(tickDelta) + MathHelper.sin(animationProgress / 30F) * 0.01F;
|
||||
|
||||
VertexConsumer buffer = vertices.getBuffer(RenderLayers.getMagicShield());
|
||||
|
||||
float thickness = 0.02F * MathHelper.sin(animationProgress / 30F);
|
||||
float alpha = 1 - Math.abs(MathHelper.sin(animationProgress / 20F)) * 0.2F;
|
||||
SphereModel.SPHERE.render(matrices, buffer, light, 1, radius + thickness, colors[0], colors[1], colors[2], alpha * 0.08F);
|
||||
SphereModel.SPHERE.render(matrices, buffer, light, 1, radius - thickness, colors[0], colors[1], colors[2], alpha * 0.05F);
|
||||
SphereModel.SPHERE.render(matrices, buffer, light, 1, radius + thickness * 2, colors[0], colors[1], colors[2], alpha * 0.05F);
|
||||
|
||||
matrices.pop();
|
||||
}
|
||||
}
|
|
@ -8,12 +8,18 @@ import java.util.stream.Stream;
|
|||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.minelittlepony.unicopia.EquinePredicates;
|
||||
import com.minelittlepony.unicopia.Unicopia;
|
||||
import com.minelittlepony.unicopia.ability.magic.Caster;
|
||||
import com.minelittlepony.unicopia.ability.magic.SpellContainer.Operation;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.Spell;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.TimedSpell;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType;
|
||||
import com.minelittlepony.unicopia.client.gui.DrawableUtil;
|
||||
import com.minelittlepony.unicopia.entity.Living;
|
||||
import com.minelittlepony.unicopia.entity.mob.CastSpellEntity;
|
||||
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
|
||||
import com.minelittlepony.unicopia.util.ColorHelper;
|
||||
|
||||
import net.fabricmc.fabric.api.resource.IdentifiableResourceReloadListener;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
|
@ -22,6 +28,7 @@ import net.minecraft.client.render.RenderLayer;
|
|||
import net.minecraft.client.render.VertexConsumer;
|
||||
import net.minecraft.client.render.VertexConsumerProvider;
|
||||
import net.minecraft.client.render.WorldRenderer;
|
||||
import net.minecraft.client.render.model.json.ModelTransformationMode;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.resource.ResourceManager;
|
||||
|
@ -31,6 +38,7 @@ import net.minecraft.util.Colors;
|
|||
import net.minecraft.util.Formatting;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.Box;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.RotationAxis;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
|
@ -43,10 +51,19 @@ public class SpellEffectsRenderDispatcher implements SynchronousResourceReloader
|
|||
REGISTRY.put(type, rendererFactory);
|
||||
}
|
||||
|
||||
static {
|
||||
register(SpellType.PLACED_SPELL, PlacedSpellRenderer::new);
|
||||
register(SpellType.SHIELD, ShieldSpellRenderer::new);
|
||||
register(SpellType.DARK_VORTEX, DarkVortexSpellRenderer::new);
|
||||
register(SpellType.BUBBLE, BubbleSpellRenderer::new);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Map<SpellType<?>, SpellRenderer<?>> renderers = Map.of();
|
||||
private final MinecraftClient client = MinecraftClient.getInstance();
|
||||
|
||||
private SpellEffectsRenderDispatcher() {}
|
||||
|
||||
@Override
|
||||
public Identifier getFabricId() {
|
||||
return ID;
|
||||
|
@ -57,12 +74,23 @@ public class SpellEffectsRenderDispatcher implements SynchronousResourceReloader
|
|||
return (SpellRenderer<S>)renderers.get(spell.getType());
|
||||
}
|
||||
|
||||
public void render(MatrixStack matrices, VertexConsumerProvider vertices, Spell spell, Caster<?> caster, int light, float limbAngle, float limbDistance, float tickDelta, float animationProgress, float headYaw, float headPitch) {
|
||||
var renderer = getRenderer(spell);
|
||||
|
||||
if (renderer != null) {
|
||||
client.getBufferBuilders().getEntityVertexConsumers().draw();
|
||||
|
||||
renderer.render(matrices, vertices, spell, caster, light, limbAngle, limbDistance, tickDelta, animationProgress, headYaw, headPitch);
|
||||
|
||||
if (EquinePredicates.IS_CASTER.test(client.player)) {
|
||||
renderGemstone(matrices, vertices, spell, caster, light, tickDelta, animationProgress);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void render(MatrixStack matrices, VertexConsumerProvider vertices, int light, Caster<?> caster, float limbAngle, float limbDistance, float tickDelta, float animationProgress, float headYaw, float headPitch) {
|
||||
caster.getSpellSlot().forEach(spell -> {
|
||||
var renderer = getRenderer(spell);
|
||||
if (renderer != null) {
|
||||
renderer.render(matrices, vertices, spell, caster, light, limbAngle, limbDistance, tickDelta, animationProgress, headYaw, headPitch);
|
||||
}
|
||||
render(matrices, vertices, spell, caster, light, limbAngle, limbDistance, tickDelta, animationProgress, headYaw, headPitch);
|
||||
return Operation.SKIP;
|
||||
}, false);
|
||||
|
||||
|
@ -77,6 +105,38 @@ public class SpellEffectsRenderDispatcher implements SynchronousResourceReloader
|
|||
renderers = REGISTRY.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().create()));
|
||||
}
|
||||
|
||||
private void renderGemstone(MatrixStack matrices, VertexConsumerProvider vertices, Spell spell, Caster<?> caster, int light, float tickDelta, float animationProgress) {
|
||||
matrices.push();
|
||||
|
||||
if (!(caster.asEntity() instanceof MagicProjectileEntity)) {
|
||||
|
||||
float y = -caster.asEntity().getHeight();
|
||||
if (caster.asEntity() instanceof CastSpellEntity) {
|
||||
y = 1F;
|
||||
}
|
||||
|
||||
matrices.translate(0, y + MathHelper.sin(animationProgress / 3F) * 0.2F, 0);
|
||||
matrices.push();
|
||||
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(animationProgress));
|
||||
|
||||
client.getItemRenderer().renderItem(spell.getType().withTraits(spell.getTraits()).getDefaultStack(), ModelTransformationMode.FIXED, light, 0, matrices, vertices, caster.asWorld(), 0);
|
||||
matrices.pop();
|
||||
|
||||
if (spell instanceof TimedSpell timed && spell.getType() != SpellType.DARK_VORTEX) {
|
||||
matrices.multiply(client.getEntityRenderDispatcher().getRotation().invert());
|
||||
float radius = 0.6F;
|
||||
float timeRemaining = timed.getTimer().getPercentTimeRemaining(tickDelta);
|
||||
|
||||
DrawableUtil.drawArc(matrices, radius, radius + 0.3F, 0, DrawableUtil.TAU * timeRemaining,
|
||||
ColorHelper.lerp(MathHelper.clamp(timeRemaining * 4, 0, 1), 0xFF0000FF, 0xFFFFFFFF),
|
||||
false
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
matrices.pop();
|
||||
}
|
||||
|
||||
private void renderSpellDebugInfo(MatrixStack matrices, VertexConsumerProvider vertices, Caster<?> caster, int light) {
|
||||
matrices.push();
|
||||
matrices.multiply(client.getEntityRenderDispatcher().getRotation());
|
||||
|
|
|
@ -37,6 +37,7 @@ public class CastSpellEntity extends LightEmittingEntity implements Caster<CastS
|
|||
|
||||
public CastSpellEntity(EntityType<?> type, World world) {
|
||||
super(type, world);
|
||||
ignoreCameraFrustum = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -5,6 +5,7 @@ import java.util.Optional;
|
|||
import com.minelittlepony.common.util.animation.MotionCompositor;
|
||||
import com.minelittlepony.unicopia.ability.magic.SpellPredicate;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.AbstractDisguiseSpell;
|
||||
import com.minelittlepony.unicopia.client.render.spell.DarkVortexSpellRenderer;
|
||||
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
|
@ -62,6 +63,7 @@ public class PlayerCamera extends MotionCompositor {
|
|||
public double calculateFieldOfView(double fov) {
|
||||
fov += player.getMagicalReserves().getExertion().get() / 5F;
|
||||
fov += getEnergyAddition();
|
||||
fov += DarkVortexSpellRenderer.getCameraDistortion() * 2.5F;
|
||||
|
||||
return fov;
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@ public class FriendshipBraceletItem extends WearableItem implements DyeableItem,
|
|||
|
||||
@Override
|
||||
public EquipmentSlot getSlotType(ItemStack stack) {
|
||||
return isSigned(stack) ? EquipmentSlot.CHEST : super.getSlotType();
|
||||
return isSigned(stack) ? EquipmentSlot.CHEST : super.getSlotType(stack);
|
||||
}
|
||||
|
||||
private boolean checkSignature(ItemStack stack, PlayerEntity player) {
|
||||
|
|
|
@ -49,6 +49,7 @@ public abstract class WearableItem extends Item implements Equipment {
|
|||
return ArmorMaterials.LEATHER.getEquipSound();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public final EquipmentSlot getSlotType() {
|
||||
return getSlotType(getDefaultStack());
|
||||
|
|
|
@ -1,19 +1,9 @@
|
|||
package com.minelittlepony.unicopia.mixin.client;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
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.client.render.AccessoryFeatureRenderer;
|
||||
|
||||
import net.minecraft.client.render.VertexConsumerProvider;
|
||||
import net.minecraft.client.render.entity.feature.ArmorFeatureRenderer;
|
||||
import net.minecraft.client.render.entity.feature.FeatureRenderer;
|
||||
import net.minecraft.client.render.entity.feature.FeatureRendererContext;
|
||||
import net.minecraft.client.render.entity.model.BipedEntityModel;
|
||||
import net.minecraft.client.render.model.BakedModelManager;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
|
||||
@Mixin(ArmorFeatureRenderer.class)
|
||||
|
@ -21,13 +11,13 @@ abstract class MixinArmorFeatureRenderer<
|
|||
T extends LivingEntity,
|
||||
M extends BipedEntityModel<T>,
|
||||
A extends BipedEntityModel<T>>
|
||||
extends FeatureRenderer<T, M> implements AccessoryFeatureRenderer.FeatureRoot<T, M> {
|
||||
extends FeatureRenderer<T, M>/* implements AccessoryFeatureRenderer.FeatureRoot<T, M>*/ {
|
||||
|
||||
private AccessoryFeatureRenderer<T, M> accessories;
|
||||
//private AccessoryFeatureRenderer<T, M> accessories;
|
||||
|
||||
MixinArmorFeatureRenderer() { super(null); }
|
||||
|
||||
@Override
|
||||
/*@Override
|
||||
public AccessoryFeatureRenderer<T, M> getAccessories() {
|
||||
return accessories;
|
||||
}
|
||||
|
@ -40,5 +30,5 @@ abstract class MixinArmorFeatureRenderer<
|
|||
@Inject(method = "render", at = @At("RETURN"))
|
||||
private void onRender(MatrixStack stack, VertexConsumerProvider renderContext, int lightUv, T entity, float limbDistance, float limbAngle, float tickDelta, float age, float headYaw, float headPitch, CallbackInfo info) {
|
||||
getAccessories().render(stack, renderContext, lightUv, entity, limbDistance, limbAngle, tickDelta, age, headYaw, headPitch);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
|
|
@ -1,17 +1,25 @@
|
|||
package com.minelittlepony.unicopia.mixin.client;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
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.At.Shift;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import com.minelittlepony.unicopia.client.render.AccessoryFeatureRenderer;
|
||||
import com.minelittlepony.unicopia.client.render.AnimalPoser;
|
||||
import com.minelittlepony.unicopia.client.render.PlayerPoser;
|
||||
import com.minelittlepony.unicopia.client.render.AccessoryFeatureRenderer.FeatureRoot;
|
||||
|
||||
import net.minecraft.client.render.VertexConsumerProvider;
|
||||
import net.minecraft.client.render.entity.EntityRenderer;
|
||||
import net.minecraft.client.render.entity.LivingEntityRenderer;
|
||||
import net.minecraft.client.render.entity.feature.FeatureRenderer;
|
||||
import net.minecraft.client.render.entity.feature.FeatureRendererContext;
|
||||
import net.minecraft.client.render.entity.model.BipedEntityModel;
|
||||
import net.minecraft.client.render.entity.model.EntityModel;
|
||||
|
@ -21,8 +29,31 @@ import net.minecraft.entity.mob.MobEntity;
|
|||
import net.minecraft.entity.player.PlayerEntity;
|
||||
|
||||
@Mixin(LivingEntityRenderer.class)
|
||||
abstract class MixinLivingEntityRenderer<T extends LivingEntity, M extends EntityModel<T>> extends EntityRenderer<T> implements FeatureRendererContext<T, M> {
|
||||
abstract class MixinLivingEntityRenderer<T extends LivingEntity, M extends EntityModel<T>> extends EntityRenderer<T>
|
||||
implements FeatureRendererContext<T, M>, FeatureRoot<T, M> {
|
||||
@Shadow
|
||||
private @Final List<FeatureRenderer<T, M>> features;
|
||||
|
||||
MixinLivingEntityRenderer() { super(null); }
|
||||
@Nullable
|
||||
private AccessoryFeatureRenderer<T, M> accessories;
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public AccessoryFeatureRenderer<T, M> getAccessories() {
|
||||
if (accessories == null) {
|
||||
accessories = features.stream()
|
||||
.filter(a -> a instanceof FeatureRoot)
|
||||
.map(a -> ((FeatureRoot<T, M>)a).getAccessories())
|
||||
.findFirst()
|
||||
.orElseGet(() -> {
|
||||
var feature = new AccessoryFeatureRenderer<>(this);
|
||||
features.add(feature);
|
||||
return feature;
|
||||
});
|
||||
}
|
||||
return accessories;
|
||||
}
|
||||
|
||||
@Inject(method = "render",
|
||||
at = @At(
|
||||
|
@ -36,6 +67,7 @@ abstract class MixinLivingEntityRenderer<T extends LivingEntity, M extends Entit
|
|||
VertexConsumerProvider vertices,
|
||||
int light,
|
||||
CallbackInfo into) {
|
||||
getAccessories();
|
||||
if (entity instanceof PlayerEntity player) {
|
||||
PlayerPoser.INSTANCE.applyPosing(matrices, player, (BipedEntityModel<?>)getModel(), PlayerPoser.Context.THIRD_PERSON);
|
||||
}
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
package com.minelittlepony.unicopia.mixin.client;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.At.Shift;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import com.minelittlepony.unicopia.client.render.AccessoryFeatureRenderer;
|
||||
import com.minelittlepony.unicopia.client.render.PlayerPoser;
|
||||
import com.minelittlepony.unicopia.client.render.AccessoryFeatureRenderer.FeatureRoot;
|
||||
|
||||
|
@ -21,31 +19,14 @@ import net.minecraft.client.util.math.MatrixStack;
|
|||
import net.minecraft.util.Arm;
|
||||
|
||||
@Mixin(PlayerEntityRenderer.class)
|
||||
abstract class MixinPlayerEntityRenderer
|
||||
extends LivingEntityRenderer<AbstractClientPlayerEntity, PlayerEntityModel<AbstractClientPlayerEntity>>
|
||||
implements FeatureRoot<AbstractClientPlayerEntity, PlayerEntityModel<AbstractClientPlayerEntity>> {
|
||||
@Nullable
|
||||
private AccessoryFeatureRenderer<AbstractClientPlayerEntity, PlayerEntityModel<AbstractClientPlayerEntity>> accessories;
|
||||
|
||||
abstract class MixinPlayerEntityRenderer extends LivingEntityRenderer<AbstractClientPlayerEntity, PlayerEntityModel<AbstractClientPlayerEntity>> {
|
||||
MixinPlayerEntityRenderer() { super(null, null, 0); }
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public AccessoryFeatureRenderer<AbstractClientPlayerEntity, PlayerEntityModel<AbstractClientPlayerEntity>> getAccessories() {
|
||||
if (accessories == null) {
|
||||
accessories = features.stream()
|
||||
.filter(a -> a instanceof FeatureRoot)
|
||||
.map(a -> ((FeatureRoot<AbstractClientPlayerEntity, PlayerEntityModel<AbstractClientPlayerEntity>>)a).getAccessories())
|
||||
.findFirst()
|
||||
.orElseGet(() -> new AccessoryFeatureRenderer<>(this));
|
||||
}
|
||||
return accessories;
|
||||
}
|
||||
|
||||
@Inject(method = "renderArm", at = @At("RETURN"))
|
||||
private void onRenderArm(MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, AbstractClientPlayerEntity player, ModelPart arm, ModelPart sleeve, CallbackInfo info) {
|
||||
Arm a = this.getModel().leftArm == arm ? Arm.LEFT : Arm.RIGHT;
|
||||
getAccessories().renderArm(matrices, vertexConsumers, light, player, arm, a);
|
||||
((FeatureRoot<AbstractClientPlayerEntity, PlayerEntityModel<AbstractClientPlayerEntity>>)this).getAccessories().renderArm(matrices, vertexConsumers, light, player, arm, a);
|
||||
}
|
||||
|
||||
@Inject(method = "renderArm",
|
||||
|
|
|
@ -136,7 +136,7 @@ public class EffectSync implements SpellContainer, NbtSerialisable {
|
|||
@SuppressWarnings("unchecked")
|
||||
private <T extends Spell> Stream<T> read(@Nullable SpellPredicate<T> type, boolean synchronize, boolean sendUpdate) {
|
||||
if (synchronize && spells.fromNbt(owner.asEntity().getDataTracker().get(param)) && sendUpdate) {
|
||||
owner.asEntity().getDataTracker().set(param, spells.toNbt());
|
||||
write();
|
||||
}
|
||||
|
||||
if (type == null) {
|
||||
|
|
|
@ -20,6 +20,7 @@ import net.minecraft.world.World;
|
|||
/**
|
||||
* A connection class for updating and persisting an attached particle effect.
|
||||
*/
|
||||
@Deprecated
|
||||
public class ParticleHandle {
|
||||
private final Map<String, Attachment> loadedEffects = new WeakHashMap<>();
|
||||
|
||||
|
|
|
@ -12,10 +12,12 @@ public interface UParticles {
|
|||
|
||||
ParticleType<MagicParticleEffect> UNICORN_MAGIC = register("unicorn_magic", FabricParticleTypes.complex(MagicParticleEffect.FACTORY));
|
||||
DefaultParticleType CHANGELING_MAGIC = register("changeling_magic", FabricParticleTypes.simple());
|
||||
DefaultParticleType BUBBLE = register("bubble", FabricParticleTypes.simple());
|
||||
|
||||
ParticleType<OrientedBillboardParticleEffect> RAINBOOM_RING = register("rainboom_ring", FabricParticleTypes.complex(OrientedBillboardParticleEffect.FACTORY));
|
||||
DefaultParticleType RAINBOOM_TRAIL = register("rainboom_trail", FabricParticleTypes.simple());
|
||||
|
||||
@Deprecated
|
||||
ParticleType<OrientedBillboardParticleEffect> MAGIC_RUNES = register("magic_runes", FabricParticleTypes.complex(OrientedBillboardParticleEffect.FACTORY));
|
||||
|
||||
DefaultParticleType RAIN_DROPS = register("rain_drops", FabricParticleTypes.simple());
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package com.minelittlepony.unicopia.util.shape;
|
||||
|
||||
import org.spongepowered.include.com.google.common.base.Objects;
|
||||
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.math.random.Random;
|
||||
|
@ -102,6 +104,19 @@ public class Sphere implements Shape {
|
|||
return stretch.multiply(rad);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
return other instanceof Sphere o
|
||||
&& Objects.equal(stretch, o.stretch)
|
||||
&& hollow == o.hollow
|
||||
&& Double.compare(rad, o.rad) == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(stretch, hollow, rad);
|
||||
}
|
||||
|
||||
public static double computeEllipsoidArea(double rad, Vec3d stretch) {
|
||||
double p = 1.6075;
|
||||
double result = Math.pow(rad * stretch.x, p) * Math.pow(rad * stretch.y, p);
|
||||
|
|
5
src/main/resources/assets/unicopia/particles/bubble.json
Normal file
5
src/main/resources/assets/unicopia/particles/bubble.json
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"textures": [
|
||||
"minecraft:bubble"
|
||||
]
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 54 KiB |
|
@ -2,13 +2,13 @@
|
|||
"parent": "unicopia:unicopia/earth/born_on_a_rock_farm",
|
||||
"display": {
|
||||
"icon": {
|
||||
"item": "unicopia:rock"
|
||||
"item": "unicopia:iron_horse_shoe"
|
||||
},
|
||||
"title": {
|
||||
"translate": "advancements.unicopia.sticks_and_stones.title"
|
||||
"translate": "advancements.unicopia.dead_ringer.title"
|
||||
},
|
||||
"description": {
|
||||
"translate": "advancements.unicopia.sticks_and_stones.description"
|
||||
"translate": "advancements.unicopia.dead_ringer.description"
|
||||
},
|
||||
"frame": "task",
|
||||
"show_toast": true,
|
||||
|
@ -16,13 +16,13 @@
|
|||
"hidden": true
|
||||
},
|
||||
"criteria": {
|
||||
"killed_entity_with_rock": {
|
||||
"killed_entity_with_horseshoe": {
|
||||
"trigger": "minecraft:player_killed_entity",
|
||||
"conditions": {
|
||||
"killing_blow": {
|
||||
"tags": [
|
||||
{
|
||||
"id": "unicopia:from_rocks",
|
||||
"id": "unicopia:from_horseshoes",
|
||||
"expected": true
|
||||
}
|
||||
]
|
||||
|
@ -31,6 +31,6 @@
|
|||
}
|
||||
},
|
||||
"requirements": [
|
||||
[ "killed_entity_with_rock" ]
|
||||
[ "killed_entity_with_horseshoe" ]
|
||||
]
|
||||
}
|
||||
|
|
|
@ -2,13 +2,13 @@
|
|||
"parent": "unicopia:unicopia/earth/born_on_a_rock_farm",
|
||||
"display": {
|
||||
"icon": {
|
||||
"item": "unicopia:horseshoe"
|
||||
"item": "unicopia:rock"
|
||||
},
|
||||
"title": {
|
||||
"translate": "advancements.unicopia.dead_ringer.title"
|
||||
"translate": "advancements.unicopia.sticks_and_stones.title"
|
||||
},
|
||||
"description": {
|
||||
"translate": "advancements.unicopia.dead_ringer.description"
|
||||
"translate": "advancements.unicopia.sticks_and_stones.description"
|
||||
},
|
||||
"frame": "task",
|
||||
"show_toast": true,
|
||||
|
@ -16,13 +16,13 @@
|
|||
"hidden": true
|
||||
},
|
||||
"criteria": {
|
||||
"killed_entity_with_horseshoe": {
|
||||
"killed_entity_with_rock": {
|
||||
"trigger": "minecraft:player_killed_entity",
|
||||
"conditions": {
|
||||
"killing_blow": {
|
||||
"tags": [
|
||||
{
|
||||
"id": "unicopia:from_horseshoes",
|
||||
"id": "unicopia:from_rocks",
|
||||
"expected": true
|
||||
}
|
||||
]
|
||||
|
@ -31,6 +31,6 @@
|
|||
}
|
||||
},
|
||||
"requirements": [
|
||||
[ "killed_entity_with_horseshoe" ]
|
||||
[ "killed_entity_with_rock" ]
|
||||
]
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue