mirror of
https://github.com/Sollace/Unicopia.git
synced 2024-11-23 21:38:00 +01:00
Rewrite the dark vortex to cause less lag and adjust/apply a cap to its maximum size
This commit is contained in:
parent
835834a468
commit
12bc0b6973
8 changed files with 205 additions and 134 deletions
|
@ -1,8 +1,12 @@
|
||||||
package com.minelittlepony.unicopia.ability.magic.spell.effect;
|
package com.minelittlepony.unicopia.ability.magic.spell.effect;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.USounds;
|
import com.minelittlepony.unicopia.USounds;
|
||||||
|
import com.minelittlepony.unicopia.UTags;
|
||||||
|
import com.minelittlepony.unicopia.Unicopia;
|
||||||
import com.minelittlepony.unicopia.ability.magic.Affine;
|
import com.minelittlepony.unicopia.ability.magic.Affine;
|
||||||
import com.minelittlepony.unicopia.ability.magic.Caster;
|
import com.minelittlepony.unicopia.ability.magic.Caster;
|
||||||
import com.minelittlepony.unicopia.ability.magic.spell.CastingMethod;
|
import com.minelittlepony.unicopia.ability.magic.spell.CastingMethod;
|
||||||
|
@ -12,6 +16,7 @@ import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits;
|
||||||
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
|
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
|
||||||
import com.minelittlepony.unicopia.entity.Living;
|
import com.minelittlepony.unicopia.entity.Living;
|
||||||
import com.minelittlepony.unicopia.entity.damage.UDamageTypes;
|
import com.minelittlepony.unicopia.entity.damage.UDamageTypes;
|
||||||
|
import com.minelittlepony.unicopia.entity.mob.CastSpellEntity;
|
||||||
import com.minelittlepony.unicopia.particle.FollowingParticleEffect;
|
import com.minelittlepony.unicopia.particle.FollowingParticleEffect;
|
||||||
import com.minelittlepony.unicopia.particle.LightningBoltParticleEffect;
|
import com.minelittlepony.unicopia.particle.LightningBoltParticleEffect;
|
||||||
import com.minelittlepony.unicopia.particle.ParticleUtils;
|
import com.minelittlepony.unicopia.particle.ParticleUtils;
|
||||||
|
@ -19,10 +24,12 @@ import com.minelittlepony.unicopia.particle.UParticles;
|
||||||
import com.minelittlepony.unicopia.projectile.MagicBeamEntity;
|
import com.minelittlepony.unicopia.projectile.MagicBeamEntity;
|
||||||
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
|
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
|
||||||
import com.minelittlepony.unicopia.projectile.ProjectileDelegate;
|
import com.minelittlepony.unicopia.projectile.ProjectileDelegate;
|
||||||
|
import com.minelittlepony.unicopia.server.world.UGameRules;
|
||||||
|
import com.minelittlepony.unicopia.util.Lerp;
|
||||||
import com.minelittlepony.unicopia.util.shape.Sphere;
|
import com.minelittlepony.unicopia.util.shape.Sphere;
|
||||||
|
|
||||||
|
import net.minecraft.block.Blocks;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.FallingBlockEntity;
|
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.entity.projectile.PersistentProjectileEntity;
|
import net.minecraft.entity.projectile.PersistentProjectileEntity;
|
||||||
import net.minecraft.item.Item;
|
import net.minecraft.item.Item;
|
||||||
|
@ -39,7 +46,7 @@ import net.minecraft.world.World.ExplosionSourceType;
|
||||||
/**
|
/**
|
||||||
* More powerful version of the vortex spell which creates a black hole.
|
* More powerful version of the vortex spell which creates a black hole.
|
||||||
*/
|
*/
|
||||||
public class DarkVortexSpell extends AttractiveSpell implements ProjectileDelegate.BlockHitListener {
|
public class DarkVortexSpell extends AbstractSpell implements ProjectileDelegate.BlockHitListener {
|
||||||
public static final SpellTraits DEFAULT_TRAITS = new SpellTraits.Builder()
|
public static final SpellTraits DEFAULT_TRAITS = new SpellTraits.Builder()
|
||||||
.with(Trait.CHAOS, 5)
|
.with(Trait.CHAOS, 5)
|
||||||
.with(Trait.KNOWLEDGE, 1)
|
.with(Trait.KNOWLEDGE, 1)
|
||||||
|
@ -49,18 +56,34 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileDelega
|
||||||
|
|
||||||
private float accumulatedMass = 0;
|
private float accumulatedMass = 0;
|
||||||
|
|
||||||
|
private final TargetSelecter targetSelecter = new TargetSelecter(this).setFilter(this::isValidTarget).setTargetowner(true).setTargetAllies(true);
|
||||||
|
|
||||||
|
private final Lerp radius = new Lerp(0);
|
||||||
|
|
||||||
|
private int prevTicksDying;
|
||||||
|
private int ticksDying;
|
||||||
|
|
||||||
protected DarkVortexSpell(CustomisedSpellType<?> type) {
|
protected DarkVortexSpell(CustomisedSpellType<?> type) {
|
||||||
super(type);
|
super(type);
|
||||||
targetSelecter.setTargetowner(true).setTargetAllies(true);
|
}
|
||||||
|
// 1. force decreases with distance: distance scale 1 -> 0
|
||||||
|
// 2. max force (at dist 0) is taken from accumulated mass
|
||||||
|
// 3. force reaches 0 at distance of drawDropOffRange
|
||||||
|
|
||||||
|
private double getMass() {
|
||||||
|
return 0.1F + accumulatedMass / 10F;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public double getEventHorizonRadius() {
|
||||||
public void onImpact(MagicProjectileEntity projectile, BlockHitResult hit) {
|
return radius.getValue();
|
||||||
if (!projectile.isClient() && projectile instanceof MagicBeamEntity source) {
|
|
||||||
BlockPos pos = hit.getBlockPos();
|
|
||||||
projectile.getWorld().createExplosion(projectile, pos.getX(), pos.getY(), pos.getZ(), 3, ExplosionSourceType.NONE);
|
|
||||||
toPlaceable().tick(source, Situation.BODY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public double getDrawDropOffRange() {
|
||||||
|
return getEventHorizonRadius() * 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
private double getAttractiveForce(Caster<?> source, Entity target) {
|
||||||
|
return AttractionUtils.getAttractiveForce(getMass(), getOrigin(source), target);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -78,23 +101,96 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileDelega
|
||||||
if (situation == Situation.BODY) {
|
if (situation == Situation.BODY) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
double mass = getMass() * 0.1;
|
||||||
|
double logarithm = 1 - (1D / (1 + (mass * mass)));
|
||||||
|
radius.update((float)Math.max(0.1, logarithm * source.asWorld().getGameRules().getInt(UGameRules.MAX_DARK_VORTEX_SIZE)), 200L);
|
||||||
|
|
||||||
if (source.asEntity().age % 20 == 0) {
|
if (source.asEntity().age % 20 == 0) {
|
||||||
source.asWorld().playSound(null, source.getOrigin(), USounds.AMBIENT_DARK_VORTEX_ADDITIONS, SoundCategory.AMBIENT, 1, 1);
|
source.asWorld().playSound(null, source.getOrigin(), USounds.AMBIENT_DARK_VORTEX_ADDITIONS, SoundCategory.AMBIENT, 1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!source.isClient() && source.asWorld().random.nextInt(300) == 0) {
|
double eventHorizon = getEventHorizonRadius();
|
||||||
|
|
||||||
|
if (source.isClient()) {
|
||||||
|
if (eventHorizon > 0.3) {
|
||||||
|
double range = eventHorizon * 2;
|
||||||
|
Vec3d origin = getOrigin(source);
|
||||||
|
source.spawnParticles(origin, new Sphere(false, range), 50, p -> {
|
||||||
|
source.addParticle(
|
||||||
|
new FollowingParticleEffect(UParticles.HEALTH_DRAIN, origin, 0.4F)
|
||||||
|
.withChild(source.asWorld().isAir(BlockPos.ofFloored(p)) ? ParticleTypes.SMOKE : ParticleTypes.CAMPFIRE_SIGNAL_SMOKE),
|
||||||
|
p,
|
||||||
|
Vec3d.ZERO
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else if (source.asWorld().random.nextInt(300) == 0) {
|
||||||
ParticleUtils.spawnParticle(source.asWorld(), LightningBoltParticleEffect.DEFAULT, getOrigin(source), Vec3d.ZERO);
|
ParticleUtils.spawnParticle(source.asWorld(), LightningBoltParticleEffect.DEFAULT, getOrigin(source), Vec3d.ZERO);
|
||||||
}
|
}
|
||||||
|
|
||||||
super.tick(source, situation);
|
if (!source.isClient()) {
|
||||||
|
if (eventHorizon > 2) {
|
||||||
|
Vec3d origin = getOrigin(source);
|
||||||
|
new Sphere(false, eventHorizon + 3).translate(origin).randomPoints(10, source.asWorld().random).forEach(i -> {
|
||||||
|
BlockPos pos = BlockPos.ofFloored(i);
|
||||||
|
if (!source.asWorld().isAir(pos)) {
|
||||||
|
new Sphere(false, 3).translate(i).getBlockPositions().forEach(p -> {
|
||||||
|
affectBlock(source, p, origin);
|
||||||
|
});
|
||||||
|
ParticleUtils.spawnParticle(source.asWorld(), new LightningBoltParticleEffect(true, 10, 6, 3, Optional.of(i)), getOrigin(source), Vec3d.ZERO);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec3d origin = getOrigin(source);
|
||||||
|
for (Entity insideEntity : source.findAllEntitiesInRange(eventHorizon * 0.5F).toList()) {
|
||||||
|
insideEntity.setVelocity(Vec3d.ZERO);
|
||||||
|
Living.updateVelocity(insideEntity);
|
||||||
|
|
||||||
|
if (insideEntity instanceof CastSpellEntity s && getType().isOn(insideEntity)) {
|
||||||
|
setDead();
|
||||||
|
s.getSpellSlot().clear();
|
||||||
|
source.asWorld().createExplosion(source.asEntity(), source.getOrigin().getX(), source.getOrigin().getY(), source.getOrigin().getZ(), 12, ExplosionSourceType.NONE);
|
||||||
|
source.asWorld().createExplosion(source.asEntity(), insideEntity.getX(), insideEntity.getY(), insideEntity.getZ(), 12, ExplosionSourceType.NONE);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
targetSelecter.getEntities(source, getDrawDropOffRange()).forEach(i -> {
|
||||||
|
try {
|
||||||
|
affectEntity(source, i, i.getPos().distanceTo(origin));
|
||||||
|
} catch (Throwable e) {
|
||||||
|
Unicopia.LOGGER.error("Error updating radial effect", e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!source.subtractEnergyCost(-accumulatedMass)) {
|
||||||
|
setDead();
|
||||||
|
source.asWorld().createExplosion(source.asEntity(), source.getOrigin().getX(), source.getOrigin().getY(), source.getOrigin().getZ(), 3, ExplosionSourceType.NONE);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void consumeManage(Caster<?> source, long costMultiplier, float knowledge) {
|
public void tickDying(Caster<?> source) {
|
||||||
if (!source.subtractEnergyCost(-accumulatedMass)) {
|
accumulatedMass /= 2D;
|
||||||
setDead();
|
double mass = getMass() * 0.1;
|
||||||
|
double logarithm = 1 - (1D / (1 + (mass * mass)));
|
||||||
|
radius.update((float)Math.max(0.1, logarithm * source.asWorld().getGameRules().getInt(UGameRules.MAX_DARK_VORTEX_SIZE)), 200L);
|
||||||
|
prevTicksDying = ticksDying;
|
||||||
|
if (ticksDying++ > 25) {
|
||||||
|
super.tickDying(source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onImpact(MagicProjectileEntity projectile, BlockHitResult hit) {
|
||||||
|
if (!projectile.isClient() && projectile instanceof MagicBeamEntity source) {
|
||||||
|
BlockPos pos = hit.getBlockPos();
|
||||||
|
projectile.getWorld().createExplosion(projectile, pos.getX(), pos.getY(), pos.getZ(), 12, ExplosionSourceType.NONE);
|
||||||
|
toPlaceable().tick(source, Situation.BODY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,102 +199,49 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileDelega
|
||||||
return accumulatedMass < 4;
|
return accumulatedMass < 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private boolean isValidTarget(Caster<?> source, Entity entity) {
|
||||||
protected boolean isValidTarget(Caster<?> source, Entity entity) {
|
|
||||||
return EntityPredicates.EXCEPT_CREATIVE_OR_SPECTATOR.test(entity) && getAttractiveForce(source, entity) > 0;
|
return EntityPredicates.EXCEPT_CREATIVE_OR_SPECTATOR.test(entity) && getAttractiveForce(source, entity) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public Vec3d getOrigin(Caster<?> source) {
|
||||||
public void generateParticles(Caster<?> source) {
|
return source.asEntity().getPos().add(0, getYOffset(), 0);
|
||||||
super.generateParticles(source);
|
|
||||||
|
|
||||||
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
|
public double getYOffset() {
|
||||||
public double getDrawDropOffRange(Caster<?> source) {
|
return 3 - radius.getValue() * 0.5;
|
||||||
return getEventHorizonRadius() * 20;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private boolean canAffect(Caster<?> source, BlockPos pos) {
|
||||||
protected Vec3d getOrigin(Caster<?> source) {
|
|
||||||
return source.getOriginVector().add(0, getEventHorizonRadius() / 2D, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected long applyEntities(Caster<?> source) {
|
|
||||||
if (!source.isClient()) {
|
|
||||||
|
|
||||||
double radius = getEventHorizonRadius();
|
|
||||||
|
|
||||||
if (radius > 2) {
|
|
||||||
Vec3d origin = getOrigin(source);
|
|
||||||
new Sphere(false, radius).translate(origin).getBlockPositions().forEach(i -> {
|
|
||||||
if (!canAffect(source, i)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (source.getOrigin().isWithinDistance(i, getEventHorizonRadius() / 2)) {
|
|
||||||
source.asWorld().breakBlock(i, false);
|
|
||||||
} else {
|
|
||||||
CatapultSpell.createBlockEntity(source.asWorld(), i, e -> {
|
|
||||||
applyRadialEffect(source, e, e.getPos().distanceTo(origin), radius);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return super.applyEntities(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean canAffect(Caster<?> source, BlockPos pos) {
|
|
||||||
return source.canModifyAt(pos)
|
return source.canModifyAt(pos)
|
||||||
&& source.asWorld().getFluidState(pos).isEmpty()
|
&& source.asWorld().getBlockState(pos).getHardness(source.asWorld(), pos) >= 0
|
||||||
&& source.asWorld().getBlockState(pos).getHardness(source.asWorld(), pos) >= 0;
|
&& !source.asWorld().getBlockState(pos).isIn(UTags.Blocks.CATAPULT_IMMUNE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1. force decreases with distance: distance scale 1 -> 0
|
private void affectBlock(Caster<?> source, BlockPos pos, Vec3d origin) {
|
||||||
// 2. max force (at dist 0) is taken from accumulated mass
|
if (!canAffect(source, pos)) {
|
||||||
// 3. force reaches 0 at distance of drawDropOffRange
|
if (source.asWorld().getBlockState(pos).isOf(Blocks.BEDROCK)) {
|
||||||
|
source.asWorld().setBlockState(pos, Blocks.BARRIER.getDefaultState());
|
||||||
public double getEventHorizonRadius() {
|
|
||||||
return Math.sqrt(Math.max(0.001, getMass() / 3F));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private double getAttractiveForce(Caster<?> source, Entity target) {
|
|
||||||
return AttractionUtils.getAttractiveForce(getMass(), getOrigin(source), target);
|
|
||||||
}
|
|
||||||
|
|
||||||
private double getMass() {
|
|
||||||
return 0.1F + accumulatedMass / 10F;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void applyRadialEffect(Caster<?> source, Entity target, double distance, double radius) {
|
|
||||||
|
|
||||||
if (target instanceof FallingBlockEntity && source.isClient()) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (source.getOrigin().isWithinDistance(pos, getEventHorizonRadius())) {
|
||||||
if (distance <= getEventHorizonRadius() + 0.5) {
|
source.asWorld().breakBlock(pos, false);
|
||||||
target.setVelocity(target.getVelocity().multiply(distance / (2 * radius)));
|
if (!source.asWorld().getFluidState(pos).isEmpty()) {
|
||||||
if (distance < 1) {
|
source.asWorld().setBlockState(pos, Blocks.AIR.getDefaultState());
|
||||||
target.setVelocity(target.getVelocity().multiply(distance));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
CatapultSpell.createBlockEntity(source.asWorld(), pos, e -> {
|
||||||
|
e.addVelocity(0, 0.1, 0);
|
||||||
|
if (e instanceof PlayerEntity) {
|
||||||
|
affectEntity(source, e, e.getPos().distanceTo(getOrigin(source)));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void affectEntity(Caster<?> source, Entity target, double distance) {
|
||||||
|
if (distance <= getEventHorizonRadius() + 0.5) {
|
||||||
|
target.setVelocity(target.getVelocity().multiply(distance < 1 ? distance : distance / (2 * getEventHorizonRadius())));
|
||||||
Living.updateVelocity(target);
|
Living.updateVelocity(target);
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
@ -227,14 +270,18 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileDelega
|
||||||
target.damage(source.damageOf(UDamageTypes.GAVITY_WELL_RECOIL, source), Integer.MAX_VALUE);
|
target.damage(source.damageOf(UDamageTypes.GAVITY_WELL_RECOIL, source), Integer.MAX_VALUE);
|
||||||
if (!(target instanceof PlayerEntity)) {
|
if (!(target instanceof PlayerEntity)) {
|
||||||
target.discard();
|
target.discard();
|
||||||
source.asWorld().playSound(null, source.getOrigin(), USounds.ENCHANTMENT_CONSUMPTION_CONSUME, SoundCategory.AMBIENT, 2, 0.02F);
|
source.asWorld().playSound(null, target.getBlockPos(), USounds.AMBIENT_DARK_VORTEX_MOOD, SoundCategory.AMBIENT, 2, 0.002F);
|
||||||
}
|
}
|
||||||
if (target.isAlive()) {
|
if (target.isAlive()) {
|
||||||
target.damage(source.asEntity().getDamageSources().outOfWorld(), Integer.MAX_VALUE);
|
target.damage(source.asEntity().getDamageSources().outOfWorld(), Integer.MAX_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
source.subtractEnergyCost(-massOfTarget * 10);
|
source.subtractEnergyCost(-massOfTarget * 10);
|
||||||
source.asWorld().playSound(null, source.getOrigin(), USounds.AMBIENT_DARK_VORTEX_MOOD, SoundCategory.AMBIENT, 2, 0.02F);
|
|
||||||
|
if (target instanceof PlayerEntity && distance < getEventHorizonRadius() + 5) {
|
||||||
|
source.asWorld().playSound(null, target.getBlockPos(), USounds.AMBIENT_DARK_VORTEX_MOOD, SoundCategory.AMBIENT, 2, 0.02F);
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
double force = getAttractiveForce(source, target);
|
double force = getAttractiveForce(source, target);
|
||||||
|
|
||||||
|
|
|
@ -198,7 +198,7 @@ public class UHud {
|
||||||
|
|
||||||
float vortexDistortion = DarkVortexSpellRenderer.getCameraDistortion();
|
float vortexDistortion = DarkVortexSpellRenderer.getCameraDistortion();
|
||||||
|
|
||||||
if (vortexDistortion > 20) {
|
if (vortexDistortion > 25) {
|
||||||
context.fill(RenderLayers.getEndPortal(), 0, 0, scaledWidth, scaledHeight, 0);
|
context.fill(RenderLayers.getEndPortal(), 0, 0, scaledWidth, scaledHeight, 0);
|
||||||
context.getMatrices().push();
|
context.getMatrices().push();
|
||||||
context.getMatrices().translate(scaledWidth / 2, scaledHeight / 2, 0);
|
context.getMatrices().translate(scaledWidth / 2, scaledHeight / 2, 0);
|
||||||
|
@ -206,7 +206,7 @@ public class UHud {
|
||||||
context.getMatrices().pop();
|
context.getMatrices().pop();
|
||||||
return;
|
return;
|
||||||
} else if (vortexDistortion > 0) {
|
} else if (vortexDistortion > 0) {
|
||||||
context.fill(0, 0, scaledWidth, scaledHeight, (int)((vortexDistortion / 20F) * 255) << 24);
|
context.fill(0, 0, scaledWidth, scaledHeight, (int)((Math.min(20, vortexDistortion) / 20F) * 255) << 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean hasEffect = client.player.hasStatusEffect(UEffects.SUN_BLINDNESS);
|
boolean hasEffect = client.player.hasStatusEffect(UEffects.SUN_BLINDNESS);
|
||||||
|
|
|
@ -8,11 +8,11 @@ import com.minelittlepony.unicopia.client.render.RenderLayers;
|
||||||
import com.minelittlepony.unicopia.client.render.model.PlaneModel;
|
import com.minelittlepony.unicopia.client.render.model.PlaneModel;
|
||||||
import com.minelittlepony.unicopia.client.render.model.SphereModel;
|
import com.minelittlepony.unicopia.client.render.model.SphereModel;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.client.render.Camera;
|
||||||
import net.minecraft.client.render.RenderLayer;
|
import net.minecraft.client.render.RenderLayer;
|
||||||
import net.minecraft.client.render.VertexConsumer;
|
import net.minecraft.client.render.VertexConsumer;
|
||||||
import net.minecraft.client.render.VertexConsumerProvider;
|
import net.minecraft.client.render.VertexConsumerProvider;
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
import net.minecraft.entity.Entity;
|
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
import net.minecraft.util.math.RotationAxis;
|
import net.minecraft.util.math.RotationAxis;
|
||||||
|
@ -36,65 +36,79 @@ public class DarkVortexSpellRenderer extends SpellRenderer<DarkVortexSpell> {
|
||||||
|
|
||||||
@Override
|
@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) {
|
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) {
|
||||||
super.render(matrices, vertices, spell, caster, light, limbAngle, limbDistance, tickDelta, animationProgress, headYaw, headPitch);
|
Camera camera = MinecraftClient.getInstance().gameRenderer.getCamera();
|
||||||
|
|
||||||
Entity cameraEntity = MinecraftClient.getInstance().getCameraEntity();
|
|
||||||
|
|
||||||
float radius = (float)spell.getEventHorizonRadius();
|
float radius = (float)spell.getEventHorizonRadius();
|
||||||
float absDistance = (float)cameraEntity.getEyePos().distanceTo(caster.getOriginVector().add(0, 2, 0));
|
|
||||||
|
float absDistance = (float)camera.getPos().distanceTo(spell.getOrigin(caster));
|
||||||
|
|
||||||
matrices.push();
|
matrices.push();
|
||||||
matrices.translate(0, 2 + radius, 0);
|
matrices.translate(0, spell.getYOffset(), 0);
|
||||||
|
|
||||||
SphereModel.SPHERE.render(matrices, vertices.getBuffer(RenderLayers.getSolid()), light, 1, Math.min(radius * 0.6F, absDistance * 0.1F), 0, 0, 0, 1);
|
float visualRadius = Math.min(radius * 0.8F, absDistance - 1F);
|
||||||
|
|
||||||
|
SphereModel.SPHERE.render(matrices, vertices.getBuffer(RenderLayers.getSolid()), light, 1, visualRadius, 0, 0, 0, 1);
|
||||||
|
SphereModel.SPHERE.render(matrices, vertices.getBuffer(RenderLayers.getMagicColored()), light, 1, visualRadius + 0.05F, 0, 0, 0, 0.9F);
|
||||||
|
SphereModel.SPHERE.render(matrices, vertices.getBuffer(RenderLayers.getMagicColored()), light, 1, visualRadius + 0.1F, 0, 0, 0, 0.9F);
|
||||||
|
SphereModel.SPHERE.render(matrices, vertices.getBuffer(RenderLayers.getMagicColored()), light, 1, visualRadius + 0.15F, 0, 0, 0, 0.9F);
|
||||||
|
|
||||||
matrices.push();
|
matrices.push();
|
||||||
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(90));
|
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(90));
|
||||||
matrices.multiply(RotationAxis.NEGATIVE_X.rotationDegrees(90 + cameraEntity.getYaw(tickDelta)));
|
matrices.multiply(RotationAxis.NEGATIVE_X.rotationDegrees(90 + camera.getYaw()));
|
||||||
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(-cameraEntity.getPitch(tickDelta)));
|
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(-camera.getPitch()));
|
||||||
|
|
||||||
matrices.scale(0.7F, 1, 1);
|
matrices.scale(0.7F, 1, 1);
|
||||||
|
|
||||||
float distance = 1F / MathHelper.clamp((absDistance / (radius * 4)), 0.0000001F, 1);
|
float distance = 1F / MathHelper.clamp(absDistance / (radius + 7), 0.0000001F, 1);
|
||||||
distance *= distance;
|
distance *= distance;
|
||||||
if (absDistance < radius * 4) {
|
if (absDistance < radius * 4) {
|
||||||
cameraDistortion += distance;
|
cameraDistortion += distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SphereModel.DISK.render(matrices, vertices.getBuffer(RenderLayers.getEndPortal()), light, 1, radius * 0.5F, 0, 0, 0, 0);
|
||||||
|
|
||||||
|
matrices.push();
|
||||||
matrices.scale(distance, distance, distance);
|
matrices.scale(distance, distance, distance);
|
||||||
|
|
||||||
if (absDistance > radius) {
|
if (absDistance > radius) {
|
||||||
matrices.push();
|
matrices.push();
|
||||||
matrices.translate(0, -0.1F, 0);
|
matrices.translate(0, -0.1F, 0);
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
matrices.scale(1, 1, 0.796F);
|
|
||||||
float brightness = i / 10F;
|
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);
|
SphereModel.DISK.render(matrices, vertices.getBuffer(RenderLayers.getMagicNoColor()), light, 1, radius * (1 + (0.25F * i)) * 0.7F, brightness, brightness, brightness, 0.2F);
|
||||||
}
|
}
|
||||||
matrices.pop();
|
matrices.pop();
|
||||||
}
|
}
|
||||||
|
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) {
|
if (radius > 0.3F && absDistance > radius) {
|
||||||
radius *= Math.min(2, 3 + radius);
|
radius *= Math.min(2, 3 + radius);
|
||||||
|
|
||||||
matrices.scale(radius, radius, radius);
|
float processionSpeed = animationProgress * 0.02F;
|
||||||
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(90));
|
float maxProcessionAngle = 15;
|
||||||
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(animationProgress * 168));
|
|
||||||
|
float range = (float)spell.getDrawDropOffRange() / 8F;
|
||||||
|
|
||||||
|
matrices.scale(range, range, range);
|
||||||
|
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(90 + MathHelper.cos(processionSpeed) * maxProcessionAngle));
|
||||||
|
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(MathHelper.sin(processionSpeed) * maxProcessionAngle));
|
||||||
|
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(animationProgress * 18));
|
||||||
|
|
||||||
VertexConsumer buffer = vertices.getBuffer(RenderLayer.getEntityTranslucent(ACCRETION_DISK_TEXTURE));
|
VertexConsumer buffer = vertices.getBuffer(RenderLayer.getEntityTranslucent(ACCRETION_DISK_TEXTURE));
|
||||||
|
|
||||||
PlaneModel.INSTANCE.render(matrices, buffer, light, 0, 1, 1, 1, 1, 1);
|
PlaneModel.INSTANCE.render(matrices, buffer, light, 0, 1, 1, 1, 1, 1);
|
||||||
|
|
||||||
matrices.push();
|
|
||||||
matrices.scale(0.5F, 0.5F, 0.5F);
|
|
||||||
|
matrices.scale(0.9F, 0.9F, 0.9F);
|
||||||
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(33));
|
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(33));
|
||||||
|
|
||||||
PlaneModel.INSTANCE.render(matrices, buffer, light, 0, 1, 1, 1, 1, 1);
|
PlaneModel.INSTANCE.render(matrices, buffer, light, 0, 1, 1, 1, 1, 1);
|
||||||
matrices.pop();
|
|
||||||
|
|
||||||
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(45));
|
matrices.scale(0.9F, 0.9F, 0.9F);
|
||||||
|
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(33));
|
||||||
PlaneModel.INSTANCE.render(matrices, buffer, light, 0, 1, 1, 1, 1, 1);
|
PlaneModel.INSTANCE.render(matrices, buffer, light, 0, 1, 1, 1, 1, 1);
|
||||||
}
|
}
|
||||||
matrices.pop();
|
matrices.pop();
|
||||||
|
|
|
@ -14,6 +14,9 @@ import com.minelittlepony.unicopia.ability.magic.SpellContainer.Operation;
|
||||||
import com.minelittlepony.unicopia.ability.magic.spell.Spell;
|
import com.minelittlepony.unicopia.ability.magic.spell.Spell;
|
||||||
import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType;
|
import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType;
|
||||||
import com.minelittlepony.unicopia.entity.Living;
|
import com.minelittlepony.unicopia.entity.Living;
|
||||||
|
import com.minelittlepony.unicopia.entity.mob.CastSpellEntity;
|
||||||
|
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||||
|
|
||||||
import net.fabricmc.fabric.api.resource.IdentifiableResourceReloadListener;
|
import net.fabricmc.fabric.api.resource.IdentifiableResourceReloadListener;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.font.TextRenderer.TextLayerType;
|
import net.minecraft.client.font.TextRenderer.TextLayerType;
|
||||||
|
@ -91,6 +94,9 @@ public class SpellEffectsRenderDispatcher implements SynchronousResourceReloader
|
||||||
if (client.getEntityRenderDispatcher().shouldRenderHitboxes()
|
if (client.getEntityRenderDispatcher().shouldRenderHitboxes()
|
||||||
&& !client.hasReducedDebugInfo()
|
&& !client.hasReducedDebugInfo()
|
||||||
&& !(caster.asEntity() == client.cameraEntity && client.options.getPerspective() == Perspective.FIRST_PERSON)) {
|
&& !(caster.asEntity() == client.cameraEntity && client.options.getPerspective() == Perspective.FIRST_PERSON)) {
|
||||||
|
if (!(caster instanceof Pony || caster instanceof CastSpellEntity)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
renderHotspot(matrices, vertices, caster, animationProgress);
|
renderHotspot(matrices, vertices, caster, animationProgress);
|
||||||
renderSpellDebugInfo(matrices, vertices, caster, light);
|
renderSpellDebugInfo(matrices, vertices, caster, light);
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,11 @@ public class UBlockTagProvider extends FabricTagProvider.BlockTagProvider {
|
||||||
UBlocks.GOLDEN_OAK_SPROUT
|
UBlocks.GOLDEN_OAK_SPROUT
|
||||||
};
|
};
|
||||||
|
|
||||||
getOrCreateTagBuilder(UTags.Blocks.CATAPULT_IMMUNE).add(Blocks.BEDROCK).forceAddTag(BlockTags.DOORS).forceAddTag(BlockTags.TRAPDOORS);
|
getOrCreateTagBuilder(UTags.Blocks.CATAPULT_IMMUNE).add(
|
||||||
|
Blocks.STRUCTURE_VOID, Blocks.STRUCTURE_BLOCK,
|
||||||
|
Blocks.COMMAND_BLOCK, Blocks.CHAIN_COMMAND_BLOCK, Blocks.REPEATING_COMMAND_BLOCK,
|
||||||
|
Blocks.LIGHT, Blocks.JIGSAW, Blocks.BARRIER, Blocks.BEDROCK
|
||||||
|
).forceAddTag(BlockTags.DOORS).forceAddTag(BlockTags.TRAPDOORS);
|
||||||
getOrCreateTagBuilder(UTags.Blocks.BUTTERFLIES_SPAWNABLE_ON).forceAddTag(BlockTags.ANIMALS_SPAWNABLE_ON).forceAddTag(BlockTags.LEAVES).forceAddTag(BlockTags.FLOWERS).forceAddTag(BlockTags.FLOWER_POTS);
|
getOrCreateTagBuilder(UTags.Blocks.BUTTERFLIES_SPAWNABLE_ON).forceAddTag(BlockTags.ANIMALS_SPAWNABLE_ON).forceAddTag(BlockTags.LEAVES).forceAddTag(BlockTags.FLOWERS).forceAddTag(BlockTags.FLOWER_POTS);
|
||||||
getOrCreateTagBuilder(UTags.Blocks.JARS).add(UBlocks.JAR, UBlocks.CLOUD_JAR, UBlocks.STORM_JAR, UBlocks.LIGHTNING_JAR, UBlocks.ZAP_JAR);
|
getOrCreateTagBuilder(UTags.Blocks.JARS).add(UBlocks.JAR, UBlocks.CLOUD_JAR, UBlocks.STORM_JAR, UBlocks.LIGHTNING_JAR, UBlocks.ZAP_JAR);
|
||||||
getOrCreateTagBuilder(BlockTags.CROPS).add(crops);
|
getOrCreateTagBuilder(BlockTags.CROPS).add(crops);
|
||||||
|
|
|
@ -716,7 +716,7 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyTurbulance(MutableVector velocity) {
|
private void applyTurbulance(MutableVector velocity) {
|
||||||
int globalEffectStrength = MathHelper.clamp(entity.getWorld().getGameRules().getInt(UGameRules.WEATHER_EFFECTS_STRENGTH), 0, 100);
|
int globalEffectStrength = entity.getWorld().getGameRules().getInt(UGameRules.WEATHER_EFFECTS_STRENGTH);
|
||||||
float effectStrength = Math.min(1, (float)ticksInAir / MAX_TICKS_TO_WEATHER_EFFECTS) * (globalEffectStrength / 100F);
|
float effectStrength = Math.min(1, (float)ticksInAir / MAX_TICKS_TO_WEATHER_EFFECTS) * (globalEffectStrength / 100F);
|
||||||
Vec3d gust = WeatherConditions.getGustStrength(entity.getWorld(), entity.getBlockPos())
|
Vec3d gust = WeatherConditions.getGustStrength(entity.getWorld(), entity.getBlockPos())
|
||||||
.multiply(globalEffectStrength / 100D)
|
.multiply(globalEffectStrength / 100D)
|
||||||
|
|
|
@ -1,15 +1,18 @@
|
||||||
package com.minelittlepony.unicopia.server.world;
|
package com.minelittlepony.unicopia.server.world;
|
||||||
|
|
||||||
|
import net.fabricmc.fabric.api.gamerule.v1.GameRuleFactory;
|
||||||
|
import net.fabricmc.fabric.api.gamerule.v1.GameRuleRegistry;
|
||||||
import net.minecraft.world.GameRules;
|
import net.minecraft.world.GameRules;
|
||||||
import net.minecraft.world.GameRules.BooleanRule;
|
import net.minecraft.world.GameRules.BooleanRule;
|
||||||
import net.minecraft.world.GameRules.IntRule;
|
import net.minecraft.world.GameRules.IntRule;
|
||||||
|
|
||||||
public interface UGameRules {
|
public interface UGameRules {
|
||||||
GameRules.Key<BooleanRule> SWAP_TRIBE_ON_DEATH = GameRules.register("swapTribeOnDeath", GameRules.Category.SPAWNING, BooleanRule.create(false));
|
GameRules.Key<BooleanRule> SWAP_TRIBE_ON_DEATH = GameRuleRegistry.register("swapTribeOnDeath", GameRules.Category.SPAWNING, GameRuleFactory.createBooleanRule(false));
|
||||||
GameRules.Key<BooleanRule> ANNOUNCE_TRIBE_JOINS = GameRules.register("announceTribeJoins", GameRules.Category.SPAWNING, BooleanRule.create(false));
|
GameRules.Key<BooleanRule> ANNOUNCE_TRIBE_JOINS = GameRuleRegistry.register("announceTribeJoins", GameRules.Category.SPAWNING, GameRuleFactory.createBooleanRule(false));
|
||||||
GameRules.Key<BooleanRule> DO_NOCTURNAL_BAT_PONIES = GameRules.register("doNocturnalBatPonies", GameRules.Category.PLAYER, BooleanRule.create(true));
|
GameRules.Key<BooleanRule> DO_NOCTURNAL_BAT_PONIES = GameRuleRegistry.register("doNocturnalBatPonies", GameRules.Category.PLAYER, GameRuleFactory.createBooleanRule(true));
|
||||||
GameRules.Key<IntRule> WEATHER_EFFECTS_STRENGTH = GameRules.register("weatherEffectsStrength", GameRules.Category.MISC, IntRule.create(100));
|
GameRules.Key<IntRule> WEATHER_EFFECTS_STRENGTH = GameRuleRegistry.register("weatherEffectsStrength", GameRules.Category.MISC, GameRuleFactory.createIntRule(100, 0, 100));
|
||||||
GameRules.Key<BooleanRule> DO_TIME_MAGIC = GameRules.register("doTimeMagic", GameRules.Category.PLAYER, BooleanRule.create(true));
|
GameRules.Key<BooleanRule> DO_TIME_MAGIC = GameRuleRegistry.register("doTimeMagic", GameRules.Category.PLAYER, GameRuleFactory.createBooleanRule(true));
|
||||||
|
GameRules.Key<IntRule> MAX_DARK_VORTEX_SIZE = GameRuleRegistry.register("maxDarkVortexSize", GameRules.Category.PLAYER, GameRuleFactory.createIntRule(20, 1, 25));
|
||||||
|
|
||||||
static void bootstrap() { }
|
static void bootstrap() { }
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,6 @@ accessible class net/minecraft/client/render/item/HeldItemRenderer$H
|
||||||
accessible class net/minecraft/client/render/VertexConsumers$Union
|
accessible class net/minecraft/client/render/VertexConsumers$Union
|
||||||
accessible class net/minecraft/client/gui/hud/InGameHud$HeartType
|
accessible class net/minecraft/client/gui/hud/InGameHud$HeartType
|
||||||
|
|
||||||
accessible method net/minecraft/world/GameRules register (Ljava/lang/String;Lnet/minecraft/world/GameRules$Category;Lnet/minecraft/world/GameRules$Type;)Lnet/minecraft/world/GameRules$Key;
|
|
||||||
accessible method net/minecraft/world/GameRules$BooleanRule create (Z)Lnet/minecraft/world/GameRules$Type;
|
|
||||||
accessible method net/minecraft/world/GameRules$IntRule create (I)Lnet/minecraft/world/GameRules$Type;
|
|
||||||
accessible method net/minecraft/world/gen/foliage/FoliagePlacerType <init> (Lcom/mojang/serialization/Codec;)V
|
accessible method net/minecraft/world/gen/foliage/FoliagePlacerType <init> (Lcom/mojang/serialization/Codec;)V
|
||||||
|
|
||||||
accessible field net/minecraft/entity/mob/CreeperEntity CHARGED Lnet/minecraft/entity/data/TrackedData;
|
accessible field net/minecraft/entity/mob/CreeperEntity CHARGED Lnet/minecraft/entity/data/TrackedData;
|
||||||
|
|
Loading…
Reference in a new issue