Fix shields, fix black holes being offset, and remove the maximum cap on black holes sizes

This commit is contained in:
Sollace 2024-02-06 15:26:33 +00:00
parent 4e8f683737
commit f3f38aae7b
No known key found for this signature in database
GPG key ID: E52FACE7B5C773DB
9 changed files with 69 additions and 39 deletions

View file

@ -32,7 +32,11 @@ public interface Owned<E extends Entity> {
Optional<UUID> getMasterId();
default boolean isOwnerOrFriend(Entity target) {
return FriendshipBraceletItem.isComrade(this, target) || isOwnerOrVehicle(target);
return isFriend(target) || isOwnerOrVehicle(target);
}
default boolean isFriend(Entity target) {
return FriendshipBraceletItem.isComrade(this, target);
}
default boolean isOwnerOrVehicle(@Nullable Entity target) {

View file

@ -160,7 +160,7 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS
private void spawnPlacedEntity(Caster<?> source) {
CastSpellEntity entity = UEntities.CAST_SPELL.create(source.asWorld());
Vec3d pos = getPosition().orElse(position.orElse(source.getOriginVector()));
Vec3d pos = getPosition().orElse(position.orElse(source.asEntity().getPos()));
entity.updatePositionAndAngles(pos.x, pos.y, pos.z, source.asEntity().getYaw(), source.asEntity().getPitch());
PlaceableSpell copy = spell.toPlaceable();
if (spell instanceof PlacementDelegate delegate) {

View file

@ -1,11 +1,15 @@
package com.minelittlepony.unicopia.ability.magic.spell.effect;
import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.entity.Living;
import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.item.enchantment.UEnchantments;
import net.minecraft.block.Block;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.Entity;
import net.minecraft.entity.ItemEntity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
@ -17,7 +21,16 @@ public interface AttractionUtils {
}
static double getMass(Entity entity) {
return entity.getWidth() * entity.getHeight();
double baseMass = entity.getWidth() * entity.getHeight();
if (entity instanceof ItemEntity item) {
baseMass *= item.getStack().getCount();
@Nullable
Block block = Block.getBlockFromItem(item.getStack().getItem());
if (block != null) {
baseMass *= MathHelper.clamp(1 + block.getHardness(), 1, 5);
}
}
return baseMass;
}
/**

View file

@ -46,12 +46,11 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileDelega
.with(Trait.DARKNESS, 100)
.build();
private static final Vec3d SPHERE_OFFSET = new Vec3d(0, 2, 0);
private float accumulatedMass = 0;
protected DarkVortexSpell(CustomisedSpellType<?> type) {
super(type);
targetSelecter.setTargetowner(true).setTargetAllies(true);
}
@Override
@ -87,7 +86,8 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileDelega
ParticleUtils.spawnParticle(source.asWorld(), LightningBoltParticleEffect.DEFAULT, getOrigin(source), Vec3d.ZERO);
}
return super.tick(source, situation);
super.tick(source, situation);
return true;
}
@Override
@ -134,7 +134,7 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileDelega
@Override
protected Vec3d getOrigin(Caster<?> source) {
return source.getOriginVector().add(SPHERE_OFFSET);
return source.getOriginVector().add(0, getEventHorizonRadius() / 2D, 0);
}
@Override
@ -182,7 +182,7 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileDelega
}
private double getMass() {
return Math.min(15, 0.1F + accumulatedMass / 10F);
return 0.1F + accumulatedMass / 10F;
}
@Override

View file

@ -16,6 +16,7 @@ import com.minelittlepony.unicopia.particle.LightningBoltParticleEffect;
import com.minelittlepony.unicopia.particle.MagicParticleEffect;
import com.minelittlepony.unicopia.particle.ParticleUtils;
import com.minelittlepony.unicopia.projectile.ProjectileUtil;
import com.minelittlepony.unicopia.util.Lerp;
import com.minelittlepony.unicopia.util.shape.Sphere;
import net.minecraft.entity.Entity;
@ -41,13 +42,10 @@ public class ShieldSpell extends AbstractSpell {
.with(Trait.AIR, 9)
.build();
private final TargetSelecter targetSelecter = new TargetSelecter(this).setFilter(this::isValidTarget);
protected final TargetSelecter targetSelecter = new TargetSelecter(this).setFilter(this::isValidTarget);
private float prevRadius;
private float radius;
private float rangeMultiplier;
private float targetRangeMultiplier;
private final Lerp radius = new Lerp(0);
private final Lerp rangeMultiplier = new Lerp(1);
private int prevTicksDying;
private int ticksDying;
@ -69,7 +67,7 @@ public class ShieldSpell extends AbstractSpell {
protected void generateParticles(Caster<?> source) {
Vec3d origin = getOrigin(source);
source.spawnParticles(origin, new Sphere(true, radius), (int)(radius * 6), pos -> {
source.spawnParticles(origin, new Sphere(true, radius.getValue()), (int)(radius.getValue() * 6), pos -> {
source.addParticle(new MagicParticleEffect(getType().getColor()), pos, Vec3d.ZERO);
if (source.asWorld().random.nextInt(10) == 0 && source.asWorld().random.nextFloat() < source.getCorruption().getScaled(1)) {
@ -80,8 +78,7 @@ public class ShieldSpell extends AbstractSpell {
@Override
public boolean tick(Caster<?> source, Situation situation) {
prevRadius = radius;
radius = (float)getDrawDropOffRange(source);
radius.update((float)getDrawDropOffRange(source), 200L);
if (source.isClient()) {
generateParticles(source);
@ -118,7 +115,7 @@ public class ShieldSpell extends AbstractSpell {
cost *= costMultiplier / ((1 + source.getLevel().get()) * 3F);
cost /= knowledge;
cost += radius / 10F;
cost += radius.getValue() / 10F;
if (!source.subtractEnergyCost(cost)) {
setDead();
@ -126,8 +123,8 @@ public class ShieldSpell extends AbstractSpell {
}
public float getRadius(float tickDelta) {
float base = MathHelper.lerp(tickDelta, prevRadius, radius);
float scale = MathHelper.clamp(MathHelper.lerp(tickDelta, prevTicksDying, ticksDying), 0, 1);
float base = radius.getValue();
float scale = 1 - MathHelper.clamp(MathHelper.lerp(tickDelta, (float)prevTicksDying, ticksDying), 0, 1);
return base * scale;
}
@ -135,17 +132,10 @@ public class ShieldSpell extends AbstractSpell {
* Calculates the maximum radius of the shield. aka The area of effect.
*/
public double getDrawDropOffRange(Caster<?> source) {
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;
}
rangeMultiplier.update(source instanceof Pony pony && pony.asEntity().isSneaking() ? 1 : 2, 500L);
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))) / rangeMultiplier;
double range = (min + (source.getLevel().getScaled(source instanceof Pony ? 4 : 40) * (source instanceof Pony ? 2 : 10))) / rangeMultiplier.getValue();
return range;
}
@ -175,9 +165,9 @@ public class ShieldSpell extends AbstractSpell {
protected long applyEntities(Caster<?> source) {
Vec3d origin = getOrigin(source);
targetSelecter.getEntities(source, radius).forEach(i -> {
targetSelecter.getEntities(source, radius.getValue()).forEach(i -> {
try {
applyRadialEffect(source, i, i.getPos().distanceTo(origin), radius);
applyRadialEffect(source, i, i.getPos().distanceTo(origin), radius.getValue());
} catch (Throwable e) {
Unicopia.LOGGER.error("Error updating radial effect", e);
}

View file

@ -21,6 +21,9 @@ public class TargetSelecter {
private BiPredicate<Caster<?>, Entity> filter = (a, b) -> true;
private boolean targetOwner;
private boolean targetAllies;
public TargetSelecter(Spell spell) {
this.spell = spell;
}
@ -30,18 +33,34 @@ public class TargetSelecter {
return this;
}
public TargetSelecter setTargetowner(boolean targetOwner) {
this.targetOwner = targetOwner;
return this;
}
public TargetSelecter setTargetAllies(boolean targetAllies) {
this.targetAllies = targetAllies;
return this;
}
public Stream<Entity> getEntities(Caster<?> source, double radius) {
targets.values().removeIf(Target::tick);
return source.findAllEntitiesInRange(radius)
.filter(EntityPredicates.VALID_ENTITY)
.filter(EquinePredicates.EXCEPT_MAGIC_IMMUNE)
.filter(entity -> entity != source.asEntity() && validTarget(spell, source, entity) && filter.test(source, entity))
.filter(entity -> entity != source.asEntity() && checkAlliegance(spell, source, entity) && filter.test(source, entity))
.map(i -> {
targets.computeIfAbsent(i.getUuid(), Target::new);
return i;
});
}
private boolean checkAlliegance(Affine affine, Caster<?> source, Entity target) {
boolean isOwner = !targetOwner && source.isOwnerOrVehicle(target);
boolean isFriend = !targetAllies && affine.applyInversion(source, source.isFriend(target));
return !(isOwner || isFriend);
}
public long getTotalDamaged() {
return targets.values().stream().filter(Target::canHurt).count();
}

View file

@ -77,7 +77,7 @@ public class DarkVortexSpellRenderer extends SpellRenderer<DarkVortexSpell> {
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;
radius *= Math.min(2, 3 + radius);
matrices.scale(radius, radius, radius);
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(90));

View file

@ -43,9 +43,9 @@ public class ShieldSpellRenderer extends SpellRenderer<ShieldSpell> {
model.render(matrices, buffer, light, 1, radius, colors[0], colors[1], colors[2], alpha * 0.2F);
} else {
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(180));
model.render(matrices, buffer, light, 1, radius + thickness, colors[0], colors[1], colors[2], alpha * 0.08F);
model.render(matrices, buffer, light, 1, radius - thickness, colors[0], colors[1], colors[2], alpha * 0.05F);
model.render(matrices, buffer, light, 1, radius + thickness * 2, colors[0], colors[1], colors[2], alpha * 0.05F);
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();

View file

@ -105,11 +105,15 @@ public class EffectSync implements SpellContainer, NbtSerialisable {
@Override
public boolean removeWhere(Predicate<Spell> test, boolean update) {
return reduce(update, (initial, effect) -> {
if (!test.test(effect)) {
return reduce(update, (initial, spell) -> {
if (!test.test(spell)) {
return initial;
}
spells.removeReference(effect);
spell.setDead();
spell.tickDying(owner);
if (spell.isDead()) {
spells.removeReference(spell);
}
return true;
});
}