mirror of
https://github.com/Sollace/Unicopia.git
synced 2024-11-23 21:38:00 +01:00
Split kicking and stomping into separate abilities
This commit is contained in:
parent
e47743a409
commit
8aa0885112
5 changed files with 228 additions and 134 deletions
|
@ -20,6 +20,7 @@ public interface Abilities {
|
||||||
Ability<?> SHOOT = register(new UnicornProjectileAbility(), "shoot", AbilitySlot.TERTIARY);
|
Ability<?> SHOOT = register(new UnicornProjectileAbility(), "shoot", AbilitySlot.TERTIARY);
|
||||||
|
|
||||||
// earth / alicorn
|
// earth / alicorn
|
||||||
|
Ability<?> KICK = register(new EarthPonyKickAbility(), "kick", AbilitySlot.PRIMARY);
|
||||||
Ability<?> GROW = register(new EarthPonyGrowAbility(), "grow", AbilitySlot.SECONDARY);
|
Ability<?> GROW = register(new EarthPonyGrowAbility(), "grow", AbilitySlot.SECONDARY);
|
||||||
Ability<?> STOMP = register(new EarthPonyStompAbility(), "stomp", AbilitySlot.TERTIARY);
|
Ability<?> STOMP = register(new EarthPonyStompAbility(), "stomp", AbilitySlot.TERTIARY);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,190 @@
|
||||||
|
package com.minelittlepony.unicopia.ability;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.minelittlepony.unicopia.Race;
|
||||||
|
import com.minelittlepony.unicopia.TreeTraverser;
|
||||||
|
import com.minelittlepony.unicopia.TreeType;
|
||||||
|
import com.minelittlepony.unicopia.ability.data.Hit;
|
||||||
|
import com.minelittlepony.unicopia.ability.data.Pos;
|
||||||
|
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||||
|
import com.minelittlepony.unicopia.util.PosHelper;
|
||||||
|
import com.minelittlepony.unicopia.util.RayTraceHelper;
|
||||||
|
import com.minelittlepony.unicopia.util.WorldEvent;
|
||||||
|
import com.minelittlepony.unicopia.util.shape.Shape;
|
||||||
|
import com.minelittlepony.unicopia.util.shape.Sphere;
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.block.Blocks;
|
||||||
|
import net.minecraft.block.LeavesBlock;
|
||||||
|
import net.minecraft.entity.ItemEntity;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.particle.BlockStateParticleEffect;
|
||||||
|
import net.minecraft.particle.ParticleTypes;
|
||||||
|
import net.minecraft.tag.BlockTags;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.Direction;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Earth Pony kicking ability
|
||||||
|
*/
|
||||||
|
public class EarthPonyKickAbility implements Ability<Pos> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getWarmupTime(Pony player) {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCooldownTime(Pony player) {
|
||||||
|
return 50;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canUse(Race race) {
|
||||||
|
return race.canUseEarth();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getCostEstimate(Pony player) {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Pos tryActivate(Pony player) {
|
||||||
|
Optional<BlockPos> p = RayTraceHelper.doTrace(player.getMaster(), 6, 1).getBlockPos();
|
||||||
|
|
||||||
|
if (p.isPresent()) {
|
||||||
|
BlockPos pos = p.get();
|
||||||
|
BlockState state = player.getWorld().getBlockState(pos);
|
||||||
|
|
||||||
|
if (state.getBlock().isIn(BlockTags.LOGS)) {
|
||||||
|
pos = TreeTraverser.Descender.descendTree(player.getWorld(), state, pos).get();
|
||||||
|
if (TreeTraverser.Measurer.measureTree(player.getWorld(), state, pos) > 0) {
|
||||||
|
return new Pos(pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Hit.Serializer<Pos> getSerializer() {
|
||||||
|
return Pos.SERIALIZER;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void apply(Pony iplayer, Pos data) {
|
||||||
|
PlayerEntity player = iplayer.getMaster();
|
||||||
|
|
||||||
|
boolean harmed = player.getHealth() < player.getMaxHealth();
|
||||||
|
|
||||||
|
if (harmed && player.world.random.nextInt(30) == 0) {
|
||||||
|
iplayer.subtractEnergyCost(3);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (harmed || player.world.random.nextInt(5) == 0) {
|
||||||
|
|
||||||
|
if (!harmed || player.world.random.nextInt(30) == 0) {
|
||||||
|
TreeTraverser.Remover.removeTree(player.world, data.pos());
|
||||||
|
}
|
||||||
|
|
||||||
|
iplayer.subtractEnergyCost(3);
|
||||||
|
} else {
|
||||||
|
int cost = dropApples(player.world, data.pos());
|
||||||
|
|
||||||
|
if (cost > 0) {
|
||||||
|
iplayer.subtractEnergyCost(cost * 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void preApply(Pony player, AbilitySlot slot) {
|
||||||
|
player.getMagicalReserves().getExertion().add(40);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void postApply(Pony player, AbilitySlot slot) {
|
||||||
|
int timeDiff = getCooldownTime(player) - player.getAbilities().getStat(slot).getRemainingCooldown();
|
||||||
|
|
||||||
|
if (player.getMaster().getEntityWorld().getTime() % 1 == 0 || timeDiff == 0) {
|
||||||
|
spawnParticleRing(player.getMaster(), timeDiff, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void spawnParticleRing(PlayerEntity player, int timeDiff, double yVel) {
|
||||||
|
int animationTicks = timeDiff / 10;
|
||||||
|
if (animationTicks < 6) {
|
||||||
|
Shape shape = new Sphere(true, animationTicks, 1, 0, 1);
|
||||||
|
|
||||||
|
double y = 0.5 + (Math.sin(animationTicks) * 1.5);
|
||||||
|
|
||||||
|
yVel *= y * 5;
|
||||||
|
|
||||||
|
for (int i = 0; i < shape.getVolumeOfSpawnableSpace(); i++) {
|
||||||
|
Vec3d point = shape.computePoint(player.getEntityWorld().random).add(player.getPos());
|
||||||
|
player.world.addParticle(new BlockStateParticleEffect(ParticleTypes.BLOCK, Blocks.DIRT.getDefaultState()),
|
||||||
|
point.x,
|
||||||
|
point.y + y,
|
||||||
|
point.z,
|
||||||
|
0, yVel, 0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int dropApples(World w, BlockPos pos) {
|
||||||
|
BlockState log = w.getBlockState(pos);
|
||||||
|
int size = TreeTraverser.Measurer.measureTree(w, log, pos);
|
||||||
|
if (size > 0) {
|
||||||
|
|
||||||
|
List<ItemEntity> capturedDrops = Lists.newArrayList();
|
||||||
|
|
||||||
|
dropApplesPart(capturedDrops, new ArrayList<BlockPos>(), w, log, pos, 0);
|
||||||
|
|
||||||
|
capturedDrops.forEach(item -> {
|
||||||
|
item.setToDefaultPickupDelay();
|
||||||
|
w.spawnEntity(item);
|
||||||
|
});
|
||||||
|
|
||||||
|
return capturedDrops.size() / 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void dropApplesPart(List<ItemEntity> drops, List<BlockPos> done, World w, BlockState log, BlockPos pos, int level) {
|
||||||
|
if (!done.contains(pos)) {
|
||||||
|
done.add(pos);
|
||||||
|
pos = TreeTraverser.Ascender.ascendTree(w, log, pos, false);
|
||||||
|
if (level < 10 && TreeTraverser.isWoodOrLeaf(w, log, pos)) {
|
||||||
|
BlockState state = w.getBlockState(pos);
|
||||||
|
|
||||||
|
if (state.getBlock() instanceof LeavesBlock && w.getBlockState(pos.down()).isAir()) {
|
||||||
|
WorldEvent.play(WorldEvent.DESTROY_BLOCK, w, pos, state);
|
||||||
|
drops.add(new ItemEntity(w,
|
||||||
|
pos.getX() + w.random.nextFloat(),
|
||||||
|
pos.getY() - 0.5,
|
||||||
|
pos.getZ() + w.random.nextFloat(),
|
||||||
|
TreeType.get(log).pickRandomStack()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
PosHelper.all(pos, p -> {
|
||||||
|
dropApplesPart(drops, done, w, log, p, level + 1);
|
||||||
|
}, Direction.UP, Direction.NORTH, Direction.SOUTH, Direction.EAST, Direction.WEST);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,21 +1,11 @@
|
||||||
package com.minelittlepony.unicopia.ability;
|
package com.minelittlepony.unicopia.ability;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import com.minelittlepony.unicopia.Race;
|
import com.minelittlepony.unicopia.Race;
|
||||||
import com.minelittlepony.unicopia.TreeTraverser;
|
|
||||||
import com.minelittlepony.unicopia.TreeType;
|
|
||||||
import com.minelittlepony.unicopia.ability.data.Hit;
|
import com.minelittlepony.unicopia.ability.data.Hit;
|
||||||
import com.minelittlepony.unicopia.ability.data.Multi;
|
|
||||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||||
import com.minelittlepony.unicopia.util.MagicalDamageSource;
|
import com.minelittlepony.unicopia.util.MagicalDamageSource;
|
||||||
import com.minelittlepony.unicopia.util.PosHelper;
|
|
||||||
import com.minelittlepony.unicopia.util.RayTraceHelper;
|
|
||||||
import com.minelittlepony.unicopia.util.WorldEvent;
|
import com.minelittlepony.unicopia.util.WorldEvent;
|
||||||
import com.minelittlepony.unicopia.util.shape.Shape;
|
import com.minelittlepony.unicopia.util.shape.Shape;
|
||||||
import com.minelittlepony.unicopia.util.shape.Sphere;
|
import com.minelittlepony.unicopia.util.shape.Sphere;
|
||||||
|
@ -23,26 +13,22 @@ import com.minelittlepony.unicopia.util.shape.Sphere;
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.block.Blocks;
|
import net.minecraft.block.Blocks;
|
||||||
import net.minecraft.block.LeavesBlock;
|
|
||||||
import net.minecraft.block.ShapeContext;
|
import net.minecraft.block.ShapeContext;
|
||||||
import net.minecraft.entity.ItemEntity;
|
|
||||||
import net.minecraft.entity.attribute.EntityAttributes;
|
import net.minecraft.entity.attribute.EntityAttributes;
|
||||||
import net.minecraft.entity.damage.DamageSource;
|
import net.minecraft.entity.damage.DamageSource;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.particle.BlockStateParticleEffect;
|
import net.minecraft.particle.BlockStateParticleEffect;
|
||||||
import net.minecraft.particle.ParticleTypes;
|
import net.minecraft.particle.ParticleTypes;
|
||||||
import net.minecraft.tag.BlockTags;
|
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.Box;
|
import net.minecraft.util.math.Box;
|
||||||
import net.minecraft.util.math.Direction;
|
import net.minecraft.util.math.Direction;
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
import net.minecraft.util.math.Vec3i;
|
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Earth Pony stomping ability
|
* Earth Pony stomping ability
|
||||||
*/
|
*/
|
||||||
public class EarthPonyStompAbility implements Ability<Multi> {
|
public class EarthPonyStompAbility implements Ability<Hit> {
|
||||||
|
|
||||||
private final double rad = 4;
|
private final double rad = 4;
|
||||||
|
|
||||||
|
@ -73,109 +59,69 @@ public class EarthPonyStompAbility implements Ability<Multi> {
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public Multi tryActivate(Pony player) {
|
public Hit tryActivate(Pony player) {
|
||||||
Optional<BlockPos> p = RayTraceHelper.doTrace(player.getMaster(), 6, 1).getBlockPos();
|
|
||||||
|
|
||||||
if (p.isPresent()) {
|
|
||||||
BlockPos pos = p.get();
|
|
||||||
BlockState state = player.getWorld().getBlockState(pos);
|
|
||||||
|
|
||||||
if (state.getBlock().isIn(BlockTags.LOGS)) {
|
|
||||||
pos = TreeTraverser.Descender.descendTree(player.getWorld(), state, pos).get();
|
|
||||||
if (TreeTraverser.Measurer.measureTree(player.getWorld(), state, pos) > 0) {
|
|
||||||
return new Multi(pos, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!player.getMaster().isOnGround() && !player.getMaster().abilities.flying) {
|
if (!player.getMaster().isOnGround() && !player.getMaster().abilities.flying) {
|
||||||
player.getMaster().addVelocity(0, -6, 0);
|
player.getMaster().addVelocity(0, -6, 0);
|
||||||
return new Multi(Vec3i.ZERO, 0);
|
return Hit.INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Hit.Serializer<Multi> getSerializer() {
|
public Hit.Serializer<Hit> getSerializer() {
|
||||||
return Multi.SERIALIZER;
|
return Hit.SERIALIZER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void apply(Pony iplayer, Multi data) {
|
public void apply(Pony iplayer, Hit data) {
|
||||||
PlayerEntity player = iplayer.getMaster();
|
PlayerEntity player = iplayer.getMaster();
|
||||||
|
|
||||||
if (data.hitType == 0) {
|
BlockPos ppos = player.getBlockPos();
|
||||||
BlockPos ppos = player.getBlockPos();
|
BlockPos pos = getSolidBlockBelow(ppos, player.getEntityWorld());
|
||||||
BlockPos pos = getSolidBlockBelow(ppos, player.getEntityWorld());
|
|
||||||
|
|
||||||
player.addVelocity(0, -(ppos.getSquaredDistance(pos)), 0);
|
player.addVelocity(0, -(ppos.getSquaredDistance(pos)), 0);
|
||||||
|
|
||||||
iplayer.getWorld().getOtherEntities(player, areaOfEffect.offset(iplayer.getOriginVector())).forEach(i -> {
|
iplayer.getWorld().getOtherEntities(player, areaOfEffect.offset(iplayer.getOriginVector())).forEach(i -> {
|
||||||
double dist = Math.sqrt(pos.getSquaredDistance(i.getBlockPos()));
|
double dist = Math.sqrt(pos.getSquaredDistance(i.getBlockPos()));
|
||||||
|
|
||||||
if (dist <= rad + 3) {
|
if (dist <= rad + 3) {
|
||||||
double force = dist / 5;
|
double force = dist / 5;
|
||||||
i.addVelocity(
|
i.addVelocity(
|
||||||
-(player.getX() - i.getX()) / force,
|
-(player.getX() - i.getX()) / force,
|
||||||
-(player.getY() - i.getY() - 2) / force + (dist < 1 ? dist : 0),
|
-(player.getY() - i.getY() - 2) / force + (dist < 1 ? dist : 0),
|
||||||
-(player.getZ() - i.getZ()) / force);
|
-(player.getZ() - i.getZ()) / force);
|
||||||
|
|
||||||
DamageSource damage = MagicalDamageSource.create("smash", player);
|
DamageSource damage = MagicalDamageSource.create("smash", player);
|
||||||
|
|
||||||
double amount = (4 * player.getAttributeInstance(EntityAttributes.GENERIC_ATTACK_DAMAGE).getValue()) / (float)dist;
|
double amount = (4 * player.getAttributeInstance(EntityAttributes.GENERIC_ATTACK_DAMAGE).getValue()) / (float)dist;
|
||||||
|
|
||||||
if (i instanceof PlayerEntity) {
|
if (i instanceof PlayerEntity) {
|
||||||
Race race = Pony.of((PlayerEntity)i).getSpecies();
|
Race race = Pony.of((PlayerEntity)i).getSpecies();
|
||||||
if (race.canUseEarth()) {
|
if (race.canUseEarth()) {
|
||||||
amount /= 3;
|
amount /= 3;
|
||||||
}
|
|
||||||
|
|
||||||
if (race.canFly()) {
|
|
||||||
amount *= 4;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
i.damage(damage, (float)amount);
|
if (race.canFly()) {
|
||||||
|
amount *= 4;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
BlockPos.iterate(pos.add(-rad, -rad, -rad), pos.add(rad, rad, rad)).forEach(i -> {
|
i.damage(damage, (float)amount);
|
||||||
if (i.getSquaredDistance(player.getX(), player.getY(), player.getZ(), true) <= rad*rad) {
|
|
||||||
spawnEffect(player.world, i);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
for (int i = 1; i < 202; i+= 2) {
|
|
||||||
spawnParticleRing(player, i, 0);
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
iplayer.subtractEnergyCost(rad);
|
BlockPos.iterate(pos.add(-rad, -rad, -rad), pos.add(rad, rad, rad)).forEach(i -> {
|
||||||
} else if (data.hitType == 1) {
|
if (i.getSquaredDistance(player.getX(), player.getY(), player.getZ(), true) <= rad*rad) {
|
||||||
|
spawnEffect(player.world, i);
|
||||||
boolean harmed = player.getHealth() < player.getMaxHealth();
|
|
||||||
|
|
||||||
if (harmed && player.world.random.nextInt(30) == 0) {
|
|
||||||
iplayer.subtractEnergyCost(3);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if (harmed || player.world.random.nextInt(5) == 0) {
|
for (int i = 1; i < 202; i+= 2) {
|
||||||
|
spawnParticleRing(player, i, 0);
|
||||||
if (!harmed || player.world.random.nextInt(30) == 0) {
|
|
||||||
TreeTraverser.Remover.removeTree(player.world, data.pos());
|
|
||||||
}
|
|
||||||
|
|
||||||
iplayer.subtractEnergyCost(3);
|
|
||||||
} else {
|
|
||||||
int cost = dropApples(player.world, data.pos());
|
|
||||||
|
|
||||||
if (cost > 0) {
|
|
||||||
iplayer.subtractEnergyCost(cost * 3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iplayer.subtractEnergyCost(rad);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void spawnEffect(World w, BlockPos pos) {
|
private void spawnEffect(World w, BlockPos pos) {
|
||||||
|
@ -221,50 +167,6 @@ public class EarthPonyStompAbility implements Ability<Multi> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int dropApples(World w, BlockPos pos) {
|
|
||||||
BlockState log = w.getBlockState(pos);
|
|
||||||
int size = TreeTraverser.Measurer.measureTree(w, log, pos);
|
|
||||||
if (size > 0) {
|
|
||||||
|
|
||||||
List<ItemEntity> capturedDrops = Lists.newArrayList();
|
|
||||||
|
|
||||||
dropApplesPart(capturedDrops, new ArrayList<BlockPos>(), w, log, pos, 0);
|
|
||||||
|
|
||||||
capturedDrops.forEach(item -> {
|
|
||||||
item.setToDefaultPickupDelay();
|
|
||||||
w.spawnEntity(item);
|
|
||||||
});
|
|
||||||
|
|
||||||
return capturedDrops.size() / 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void dropApplesPart(List<ItemEntity> drops, List<BlockPos> done, World w, BlockState log, BlockPos pos, int level) {
|
|
||||||
if (!done.contains(pos)) {
|
|
||||||
done.add(pos);
|
|
||||||
pos = TreeTraverser.Ascender.ascendTree(w, log, pos, false);
|
|
||||||
if (level < 10 && TreeTraverser.isWoodOrLeaf(w, log, pos)) {
|
|
||||||
BlockState state = w.getBlockState(pos);
|
|
||||||
|
|
||||||
if (state.getBlock() instanceof LeavesBlock && w.getBlockState(pos.down()).isAir()) {
|
|
||||||
WorldEvent.play(WorldEvent.DESTROY_BLOCK, w, pos, state);
|
|
||||||
drops.add(new ItemEntity(w,
|
|
||||||
pos.getX() + w.random.nextFloat(),
|
|
||||||
pos.getY() - 0.5,
|
|
||||||
pos.getZ() + w.random.nextFloat(),
|
|
||||||
TreeType.get(log).pickRandomStack()
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
PosHelper.all(pos, p -> {
|
|
||||||
dropApplesPart(drops, done, w, log, p, level + 1);
|
|
||||||
}, Direction.UP, Direction.NORTH, Direction.SOUTH, Direction.EAST, Direction.WEST);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static BlockPos getSolidBlockBelow(BlockPos pos, World w) {
|
private static BlockPos getSolidBlockBelow(BlockPos pos, World w) {
|
||||||
while (!World.isHeightInvalid(pos)) {
|
while (!World.isHeightInvalid(pos)) {
|
||||||
pos = pos.down();
|
pos = pos.down();
|
||||||
|
|
|
@ -130,6 +130,7 @@
|
||||||
"ability.unicopia.teleport": "Teleport",
|
"ability.unicopia.teleport": "Teleport",
|
||||||
"ability.unicopia.grow": "Earthly Nourishment",
|
"ability.unicopia.grow": "Earthly Nourishment",
|
||||||
"ability.unicopia.stomp": "Ground Pound",
|
"ability.unicopia.stomp": "Ground Pound",
|
||||||
|
"ability.unicopia.kick": "Crushing Blow",
|
||||||
"ability.unicopia.pummel": "Crushing Blow",
|
"ability.unicopia.pummel": "Crushing Blow",
|
||||||
"ability.unicopia.carry": "Pickup/Drop Passenger",
|
"ability.unicopia.carry": "Pickup/Drop Passenger",
|
||||||
"ability.unicopia.hang": "Cling to Ceiling",
|
"ability.unicopia.hang": "Cling to Ceiling",
|
||||||
|
|
BIN
src/main/resources/assets/unicopia/textures/gui/ability/kick.png
Normal file
BIN
src/main/resources/assets/unicopia/textures/gui/ability/kick.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2 KiB |
Loading…
Reference in a new issue