mirror of
https://github.com/Sollace/Unicopia.git
synced 2025-02-25 06:04:32 +01:00
Fix shields, fix black holes being offset, and remove the maximum cap on black holes sizes
This commit is contained in:
parent
4e8f683737
commit
f3f38aae7b
9 changed files with 69 additions and 39 deletions
|
@ -32,7 +32,11 @@ public interface Owned<E extends Entity> {
|
||||||
Optional<UUID> getMasterId();
|
Optional<UUID> getMasterId();
|
||||||
|
|
||||||
default boolean isOwnerOrFriend(Entity target) {
|
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) {
|
default boolean isOwnerOrVehicle(@Nullable Entity target) {
|
||||||
|
|
|
@ -160,7 +160,7 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS
|
||||||
|
|
||||||
private void spawnPlacedEntity(Caster<?> source) {
|
private void spawnPlacedEntity(Caster<?> source) {
|
||||||
CastSpellEntity entity = UEntities.CAST_SPELL.create(source.asWorld());
|
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());
|
entity.updatePositionAndAngles(pos.x, pos.y, pos.z, source.asEntity().getYaw(), source.asEntity().getPitch());
|
||||||
PlaceableSpell copy = spell.toPlaceable();
|
PlaceableSpell copy = spell.toPlaceable();
|
||||||
if (spell instanceof PlacementDelegate delegate) {
|
if (spell instanceof PlacementDelegate delegate) {
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
package com.minelittlepony.unicopia.ability.magic.spell.effect;
|
package com.minelittlepony.unicopia.ability.magic.spell.effect;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.entity.Living;
|
import com.minelittlepony.unicopia.entity.Living;
|
||||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||||
import com.minelittlepony.unicopia.item.enchantment.UEnchantments;
|
import com.minelittlepony.unicopia.item.enchantment.UEnchantments;
|
||||||
|
|
||||||
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.enchantment.EnchantmentHelper;
|
import net.minecraft.enchantment.EnchantmentHelper;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.ItemEntity;
|
||||||
import net.minecraft.entity.LivingEntity;
|
import net.minecraft.entity.LivingEntity;
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
@ -17,7 +21,16 @@ public interface AttractionUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
static double getMass(Entity entity) {
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -46,12 +46,11 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileDelega
|
||||||
.with(Trait.DARKNESS, 100)
|
.with(Trait.DARKNESS, 100)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
private static final Vec3d SPHERE_OFFSET = new Vec3d(0, 2, 0);
|
|
||||||
|
|
||||||
private float accumulatedMass = 0;
|
private float accumulatedMass = 0;
|
||||||
|
|
||||||
protected DarkVortexSpell(CustomisedSpellType<?> type) {
|
protected DarkVortexSpell(CustomisedSpellType<?> type) {
|
||||||
super(type);
|
super(type);
|
||||||
|
targetSelecter.setTargetowner(true).setTargetAllies(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -87,7 +86,8 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileDelega
|
||||||
ParticleUtils.spawnParticle(source.asWorld(), LightningBoltParticleEffect.DEFAULT, getOrigin(source), Vec3d.ZERO);
|
ParticleUtils.spawnParticle(source.asWorld(), LightningBoltParticleEffect.DEFAULT, getOrigin(source), Vec3d.ZERO);
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.tick(source, situation);
|
super.tick(source, situation);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -134,7 +134,7 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileDelega
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Vec3d getOrigin(Caster<?> source) {
|
protected Vec3d getOrigin(Caster<?> source) {
|
||||||
return source.getOriginVector().add(SPHERE_OFFSET);
|
return source.getOriginVector().add(0, getEventHorizonRadius() / 2D, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -182,7 +182,7 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileDelega
|
||||||
}
|
}
|
||||||
|
|
||||||
private double getMass() {
|
private double getMass() {
|
||||||
return Math.min(15, 0.1F + accumulatedMass / 10F);
|
return 0.1F + accumulatedMass / 10F;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -16,6 +16,7 @@ import com.minelittlepony.unicopia.particle.LightningBoltParticleEffect;
|
||||||
import com.minelittlepony.unicopia.particle.MagicParticleEffect;
|
import com.minelittlepony.unicopia.particle.MagicParticleEffect;
|
||||||
import com.minelittlepony.unicopia.particle.ParticleUtils;
|
import com.minelittlepony.unicopia.particle.ParticleUtils;
|
||||||
import com.minelittlepony.unicopia.projectile.ProjectileUtil;
|
import com.minelittlepony.unicopia.projectile.ProjectileUtil;
|
||||||
|
import com.minelittlepony.unicopia.util.Lerp;
|
||||||
import com.minelittlepony.unicopia.util.shape.Sphere;
|
import com.minelittlepony.unicopia.util.shape.Sphere;
|
||||||
|
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
|
@ -41,13 +42,10 @@ public class ShieldSpell extends AbstractSpell {
|
||||||
.with(Trait.AIR, 9)
|
.with(Trait.AIR, 9)
|
||||||
.build();
|
.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 final Lerp radius = new Lerp(0);
|
||||||
private float radius;
|
private final Lerp rangeMultiplier = new Lerp(1);
|
||||||
|
|
||||||
private float rangeMultiplier;
|
|
||||||
private float targetRangeMultiplier;
|
|
||||||
|
|
||||||
private int prevTicksDying;
|
private int prevTicksDying;
|
||||||
private int ticksDying;
|
private int ticksDying;
|
||||||
|
@ -69,7 +67,7 @@ public class ShieldSpell extends AbstractSpell {
|
||||||
protected void generateParticles(Caster<?> source) {
|
protected void generateParticles(Caster<?> source) {
|
||||||
Vec3d origin = getOrigin(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);
|
source.addParticle(new MagicParticleEffect(getType().getColor()), pos, Vec3d.ZERO);
|
||||||
|
|
||||||
if (source.asWorld().random.nextInt(10) == 0 && source.asWorld().random.nextFloat() < source.getCorruption().getScaled(1)) {
|
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
|
@Override
|
||||||
public boolean tick(Caster<?> source, Situation situation) {
|
public boolean tick(Caster<?> source, Situation situation) {
|
||||||
prevRadius = radius;
|
radius.update((float)getDrawDropOffRange(source), 200L);
|
||||||
radius = (float)getDrawDropOffRange(source);
|
|
||||||
|
|
||||||
if (source.isClient()) {
|
if (source.isClient()) {
|
||||||
generateParticles(source);
|
generateParticles(source);
|
||||||
|
@ -118,7 +115,7 @@ public class ShieldSpell extends AbstractSpell {
|
||||||
|
|
||||||
cost *= costMultiplier / ((1 + source.getLevel().get()) * 3F);
|
cost *= costMultiplier / ((1 + source.getLevel().get()) * 3F);
|
||||||
cost /= knowledge;
|
cost /= knowledge;
|
||||||
cost += radius / 10F;
|
cost += radius.getValue() / 10F;
|
||||||
|
|
||||||
if (!source.subtractEnergyCost(cost)) {
|
if (!source.subtractEnergyCost(cost)) {
|
||||||
setDead();
|
setDead();
|
||||||
|
@ -126,8 +123,8 @@ public class ShieldSpell extends AbstractSpell {
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getRadius(float tickDelta) {
|
public float getRadius(float tickDelta) {
|
||||||
float base = MathHelper.lerp(tickDelta, prevRadius, radius);
|
float base = radius.getValue();
|
||||||
float scale = MathHelper.clamp(MathHelper.lerp(tickDelta, prevTicksDying, ticksDying), 0, 1);
|
float scale = 1 - MathHelper.clamp(MathHelper.lerp(tickDelta, (float)prevTicksDying, ticksDying), 0, 1);
|
||||||
return base * scale;
|
return base * scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,17 +132,10 @@ public class ShieldSpell extends AbstractSpell {
|
||||||
* Calculates the maximum radius of the shield. aka The area of effect.
|
* Calculates the maximum radius of the shield. aka The area of effect.
|
||||||
*/
|
*/
|
||||||
public double getDrawDropOffRange(Caster<?> source) {
|
public double getDrawDropOffRange(Caster<?> source) {
|
||||||
targetRangeMultiplier = source instanceof Pony pony && pony.asEntity().isSneaking() ? 1 : 2;
|
rangeMultiplier.update(source instanceof Pony pony && pony.asEntity().isSneaking() ? 1 : 2, 500L);
|
||||||
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);
|
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;
|
return range;
|
||||||
}
|
}
|
||||||
|
@ -175,9 +165,9 @@ public class ShieldSpell extends AbstractSpell {
|
||||||
|
|
||||||
protected long applyEntities(Caster<?> source) {
|
protected long applyEntities(Caster<?> source) {
|
||||||
Vec3d origin = getOrigin(source);
|
Vec3d origin = getOrigin(source);
|
||||||
targetSelecter.getEntities(source, radius).forEach(i -> {
|
targetSelecter.getEntities(source, radius.getValue()).forEach(i -> {
|
||||||
try {
|
try {
|
||||||
applyRadialEffect(source, i, i.getPos().distanceTo(origin), radius);
|
applyRadialEffect(source, i, i.getPos().distanceTo(origin), radius.getValue());
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
Unicopia.LOGGER.error("Error updating radial effect", e);
|
Unicopia.LOGGER.error("Error updating radial effect", e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,9 @@ public class TargetSelecter {
|
||||||
|
|
||||||
private BiPredicate<Caster<?>, Entity> filter = (a, b) -> true;
|
private BiPredicate<Caster<?>, Entity> filter = (a, b) -> true;
|
||||||
|
|
||||||
|
private boolean targetOwner;
|
||||||
|
private boolean targetAllies;
|
||||||
|
|
||||||
public TargetSelecter(Spell spell) {
|
public TargetSelecter(Spell spell) {
|
||||||
this.spell = spell;
|
this.spell = spell;
|
||||||
}
|
}
|
||||||
|
@ -30,18 +33,34 @@ public class TargetSelecter {
|
||||||
return this;
|
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) {
|
public Stream<Entity> getEntities(Caster<?> source, double radius) {
|
||||||
targets.values().removeIf(Target::tick);
|
targets.values().removeIf(Target::tick);
|
||||||
return source.findAllEntitiesInRange(radius)
|
return source.findAllEntitiesInRange(radius)
|
||||||
.filter(EntityPredicates.VALID_ENTITY)
|
.filter(EntityPredicates.VALID_ENTITY)
|
||||||
.filter(EquinePredicates.EXCEPT_MAGIC_IMMUNE)
|
.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 -> {
|
.map(i -> {
|
||||||
targets.computeIfAbsent(i.getUuid(), Target::new);
|
targets.computeIfAbsent(i.getUuid(), Target::new);
|
||||||
return i;
|
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() {
|
public long getTotalDamaged() {
|
||||||
return targets.values().stream().filter(Target::canHurt).count();
|
return targets.values().stream().filter(Target::canHurt).count();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
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 *= 3 + radius;
|
radius *= Math.min(2, 3 + radius);
|
||||||
|
|
||||||
matrices.scale(radius, radius, radius);
|
matrices.scale(radius, radius, radius);
|
||||||
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(90));
|
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(90));
|
||||||
|
|
|
@ -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);
|
model.render(matrices, buffer, light, 1, radius, colors[0], colors[1], colors[2], alpha * 0.2F);
|
||||||
} else {
|
} else {
|
||||||
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(180));
|
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(180));
|
||||||
model.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.08F);
|
||||||
model.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, 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 * 2, colors[0], colors[1], colors[2], alpha * 0.05F);
|
||||||
}
|
}
|
||||||
|
|
||||||
matrices.pop();
|
matrices.pop();
|
||||||
|
|
|
@ -105,11 +105,15 @@ public class EffectSync implements SpellContainer, NbtSerialisable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean removeWhere(Predicate<Spell> test, boolean update) {
|
public boolean removeWhere(Predicate<Spell> test, boolean update) {
|
||||||
return reduce(update, (initial, effect) -> {
|
return reduce(update, (initial, spell) -> {
|
||||||
if (!test.test(effect)) {
|
if (!test.test(spell)) {
|
||||||
return initial;
|
return initial;
|
||||||
}
|
}
|
||||||
spells.removeReference(effect);
|
spell.setDead();
|
||||||
|
spell.tickDying(owner);
|
||||||
|
if (spell.isDead()) {
|
||||||
|
spells.removeReference(spell);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue