Unicopia/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyStompAbility.java

179 lines
6 KiB
Java
Raw Normal View History

package com.minelittlepony.unicopia.ability;
2018-09-12 01:29:49 +02:00
import javax.annotation.Nullable;
import com.minelittlepony.unicopia.BlockDestructionManager;
import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.ability.data.Hit;
import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.item.enchantment.UEnchantments;
import com.minelittlepony.unicopia.particle.ParticleUtils;
import com.minelittlepony.unicopia.particle.UParticles;
import com.minelittlepony.unicopia.util.MagicalDamageSource;
import com.minelittlepony.unicopia.util.PosHelper;
import com.minelittlepony.unicopia.util.WorldEvent;
2020-01-16 12:35:46 +01:00
import net.minecraft.block.BlockState;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.LivingEntity;
2020-01-16 12:35:46 +01:00
import net.minecraft.entity.attribute.EntityAttributes;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.player.PlayerEntity;
2018-09-12 01:29:49 +02:00
import net.minecraft.util.math.BlockPos;
2020-01-16 12:35:46 +01:00
import net.minecraft.util.math.Box;
import net.minecraft.util.math.MathHelper;
2018-09-12 01:29:49 +02:00
import net.minecraft.world.World;
/**
* Earth Pony stomping ability
*/
public class EarthPonyStompAbility implements Ability<Hit> {
2018-09-12 01:29:49 +02:00
2019-02-03 10:45:45 +01:00
private final double rad = 4;
2020-01-16 12:35:46 +01:00
private final Box areaOfEffect = new Box(
2019-02-03 10:45:45 +01:00
-rad, -rad, -rad,
rad, rad, rad
);
2018-09-12 01:29:49 +02:00
@Override
2020-04-15 18:12:00 +02:00
public int getWarmupTime(Pony player) {
2019-02-07 10:46:59 +01:00
return 3;
2018-09-12 01:29:49 +02:00
}
@Override
2020-04-15 18:12:00 +02:00
public int getCooldownTime(Pony player) {
2019-02-07 10:46:59 +01:00
return 50;
2018-09-12 01:29:49 +02:00
}
@Override
public boolean canUse(Race race) {
return race.canUseEarth();
2018-09-12 01:29:49 +02:00
}
@Override
public double getCostEstimate(Pony player) {
return rad;
}
@Nullable
2018-09-12 01:29:49 +02:00
@Override
public Hit tryActivate(Pony player) {
if (!player.getMaster().isOnGround() && !player.getMaster().abilities.flying) {
thrustDownwards(player.getMaster());
return Hit.INSTANCE;
2018-09-12 01:29:49 +02:00
}
2018-09-12 01:29:49 +02:00
return null;
}
@Override
public Hit.Serializer<Hit> getSerializer() {
return Hit.SERIALIZER;
2018-09-12 01:29:49 +02:00
}
private void thrustDownwards(PlayerEntity player) {
BlockPos ppos = player.getBlockPos();
BlockPos pos = PosHelper.findSolidGroundAt(player.getEntityWorld(), ppos);
double downV = Math.sqrt(ppos.getSquaredDistance(pos));
player.addVelocity(0, -downV, 0);
}
2018-09-12 01:29:49 +02:00
@Override
public void apply(Pony iplayer, Hit data) {
PlayerEntity player = iplayer.getMaster();
thrustDownwards(player);
iplayer.waitForFall(() -> {
BlockPos center = PosHelper.findSolidGroundAt(player.getEntityWorld(), player.getBlockPos());
float heavyness = 1 + EnchantmentHelper.getEquipmentLevel(UEnchantments.HEAVY, player);
iplayer.getWorld().getOtherEntities(player, areaOfEffect.offset(iplayer.getOriginVector())).forEach(i -> {
double dist = Math.sqrt(center.getSquaredDistance(i.getBlockPos()));
if (dist <= rad + 3) {
double inertia = dist / 5;
if (i instanceof LivingEntity) {
inertia *= 1 + EnchantmentHelper.getEquipmentLevel(UEnchantments.HEAVY, (LivingEntity)i);
}
inertia /= heavyness;
double liftAmount = Math.sin(Math.PI * dist / rad) * 12;
i.addVelocity(
-(player.getX() - i.getX()) / inertia,
-(player.getY() - i.getY() - liftAmount) / inertia + (dist < 1 ? dist : 0),
-(player.getZ() - i.getZ()) / inertia);
DamageSource damage = MagicalDamageSource.create("smash", player);
double amount = (4 * player.getAttributeInstance(EntityAttributes.GENERIC_ATTACK_DAMAGE).getValue() + heavyness * 0.4) / (float)dist;
if (i instanceof PlayerEntity) {
Race race = Pony.of((PlayerEntity)i).getSpecies();
if (race.canUseEarth()) {
amount /= 3;
}
if (race.canFly()) {
amount *= 4;
}
}
if (i instanceof LivingEntity) {
amount /= 1 + (EnchantmentHelper.getEquipmentLevel(UEnchantments.PADDED, (LivingEntity)i) / 6F);
}
i.damage(damage, (float)amount);
}
});
double radius = rad + heavyness * 0.3;
BlockPos.iterate(center.add(-radius, -radius, -radius), center.add(radius, radius, radius)).forEach(i -> {
double dist = Math.sqrt(i.getSquaredDistance(player.getX(), player.getY(), player.getZ(), true));
if (dist <= radius) {
spawnEffect(player.world, i, dist);
}
});
ParticleUtils.spawnParticle(player.world, UParticles.GROUND_POUND, player.getX(), player.getY() - 1, player.getZ(), 0, 0, 0);
iplayer.subtractEnergyCost(rad);
});
2018-09-12 01:29:49 +02:00
}
private void spawnEffect(World w, BlockPos pos, double dist) {
2020-01-16 12:35:46 +01:00
BlockState state = w.getBlockState(pos);
BlockDestructionManager destr = ((BlockDestructionManager.Source)w).getDestructionManager();
2018-09-12 01:29:49 +02:00
2020-01-16 12:35:46 +01:00
if (!state.isAir() && w.getBlockState(pos.up()).isAir()) {
double amount = (1 - dist / rad) * 9;
float hardness = state.getHardness(w, pos);
float scaledHardness = (1 - hardness / 70);
int damage = hardness < 0 ? 0 : MathHelper.clamp((int)(amount * scaledHardness), 2, 9);
if (destr.damageBlock(pos, damage) >= BlockDestructionManager.MAX_DAMAGE) {
w.breakBlock(pos, true);
} else {
WorldEvent.play(WorldEvent.DESTROY_BLOCK, w, pos, state);
}
2018-09-12 01:29:49 +02:00
}
}
@Override
public void preApply(Pony player, AbilitySlot slot) {
2020-10-01 17:04:48 +02:00
player.getMagicalReserves().getExertion().add(40);
2018-09-12 01:29:49 +02:00
}
@Override
public void postApply(Pony player, AbilitySlot slot) {
2018-09-12 01:29:49 +02:00
}
}