mirror of
https://github.com/Sollace/Unicopia.git
synced 2024-11-27 15:17:59 +01:00
Spells can now be attached to entities other than players
This commit is contained in:
parent
1248b93995
commit
779ae10a99
17 changed files with 289 additions and 81 deletions
|
@ -1,8 +1,10 @@
|
|||
package com.minelittlepony.unicopia.forgebullshit;
|
||||
|
||||
import com.minelittlepony.unicopia.Unicopia;
|
||||
import com.minelittlepony.unicopia.entity.IMagicals;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.item.EntityItem;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
|
@ -28,9 +30,11 @@ public class FBS {
|
|||
|
||||
@SubscribeEvent
|
||||
public static void attach(AttachCapabilitiesEvent<Entity> event) {
|
||||
if (event.getObject() instanceof EntityPlayer
|
||||
|| event.getObject() instanceof EntityItem) {
|
||||
event.addCapability(new ResourceLocation("unicopia", "race"), new Provider(event.getObject()));
|
||||
Entity obj = event.getObject();
|
||||
|
||||
if ((obj instanceof EntityLivingBase && !(obj instanceof IMagicals))
|
||||
|| obj instanceof EntityItem) {
|
||||
event.addCapability(new ResourceLocation("unicopia", "race"), new Provider(obj));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,8 @@ import javax.annotation.Nonnull;
|
|||
import javax.annotation.Nullable;
|
||||
|
||||
import com.minelittlepony.unicopia.Predicates;
|
||||
import com.minelittlepony.unicopia.power.IPower;
|
||||
import com.minelittlepony.unicopia.player.IPlayer;
|
||||
import com.minelittlepony.unicopia.player.PlayerSpeciesList;
|
||||
import com.minelittlepony.unicopia.spell.CasterUtils;
|
||||
import com.minelittlepony.unicopia.spell.IAligned;
|
||||
import com.minelittlepony.unicopia.spell.ICaster;
|
||||
|
@ -82,12 +83,10 @@ public class ItemMagicStaff extends ItemStaff implements IAligned, ITossableItem
|
|||
if (attacker.isSneaking()) {
|
||||
stack.damageItem(50, attacker);
|
||||
|
||||
if (attacker instanceof EntityPlayer) {
|
||||
IPower.takeFromPlayer((EntityPlayer)attacker, 4);
|
||||
}
|
||||
CasterUtils.toCaster(attacker).ifPresent(c -> c.subtractEnergyCost(4));
|
||||
|
||||
onImpact(
|
||||
CasterUtils.toCaster(target).orElseGet(() -> CasterUtils.near(target)),
|
||||
CasterUtils.near(target),
|
||||
target.getPosition(),
|
||||
target.getEntityWorld().getBlockState(target.getPosition())
|
||||
);
|
||||
|
@ -140,9 +139,10 @@ public class ItemMagicStaff extends ItemStaff implements IAligned, ITossableItem
|
|||
|
||||
@Override
|
||||
public void toss(World world, ItemStack stack, EntityPlayer player) {
|
||||
CasterUtils.toCaster(player).ifPresent(effect::toss);
|
||||
IPlayer iplayer = PlayerSpeciesList.instance().getPlayer(player);
|
||||
|
||||
IPower.takeFromPlayer(player, 4);
|
||||
iplayer.subtractEnergyCost(4);
|
||||
effect.toss(iplayer);
|
||||
|
||||
stack.damageItem(1, player);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,135 @@
|
|||
package com.minelittlepony.unicopia.player;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.minelittlepony.unicopia.Race;
|
||||
import com.minelittlepony.unicopia.network.EffectSync;
|
||||
import com.minelittlepony.unicopia.spell.IAligned;
|
||||
import com.minelittlepony.unicopia.spell.IAttachedEffect;
|
||||
import com.minelittlepony.unicopia.spell.ICaster;
|
||||
import com.minelittlepony.unicopia.spell.IMagicEffect;
|
||||
import com.minelittlepony.unicopia.spell.SpellAffinity;
|
||||
import com.minelittlepony.unicopia.spell.SpellRegistry;
|
||||
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.network.datasync.DataParameter;
|
||||
import net.minecraft.network.datasync.DataSerializers;
|
||||
import net.minecraft.network.datasync.EntityDataManager;
|
||||
|
||||
public class EntityCapabilities implements IRaceContainer<EntityLivingBase>, ICaster<EntityLivingBase> {
|
||||
|
||||
private static final Map<Class<? extends EntityLivingBase>, DataParameter<NBTTagCompound>> EFFECT_KEYS = Maps.newHashMap();
|
||||
|
||||
private final DataParameter<NBTTagCompound> EFFECT;
|
||||
|
||||
private final EffectSync<EntityLivingBase> effectDelegate;
|
||||
|
||||
private EntityLivingBase entity;
|
||||
|
||||
EntityCapabilities(EntityLivingBase entity) {
|
||||
setOwner(entity);
|
||||
|
||||
EFFECT = EFFECT_KEYS.computeIfAbsent(entity.getClass(), c -> {
|
||||
return EntityDataManager.createKey(c, DataSerializers.COMPOUND_TAG);
|
||||
});
|
||||
effectDelegate = new EffectSync<>(this, EFFECT);
|
||||
|
||||
entity.getDataManager().register(EFFECT, new NBTTagCompound());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Race getPlayerSpecies() {
|
||||
return Race.HUMAN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerSpecies(Race race) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEffect(IMagicEffect effect) {
|
||||
effectDelegate.set(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends IMagicEffect> T getEffect(Class<T> type, boolean update) {
|
||||
return effectDelegate.get(type, update);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasEffect() {
|
||||
return effectDelegate.has();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeUpdate() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpdate() {
|
||||
if (hasEffect()) {
|
||||
IAttachedEffect effect = getEffect(IAttachedEffect.class, true);
|
||||
|
||||
if (effect != null) {
|
||||
if (entity.getEntityWorld().isRemote) {
|
||||
effect.renderOnPerson(this);
|
||||
}
|
||||
|
||||
if (!effect.updateOnPerson(this)) {
|
||||
setEffect(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDimensionalTravel(int destinationDimension) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOwner(EntityLivingBase owner) {
|
||||
entity = owner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityLivingBase getOwner() {
|
||||
return entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCurrentLevel() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCurrentLevel(int level) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpellAffinity getAffinity() {
|
||||
if (getOwner() instanceof IAligned) {
|
||||
return ((IAligned)getOwner()).getAffinity();
|
||||
}
|
||||
return SpellAffinity.NEUTRAL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToNBT(NBTTagCompound compound) {
|
||||
IMagicEffect effect = getEffect();
|
||||
|
||||
if (effect != null) {
|
||||
compound.setTag("effect", SpellRegistry.instance().serializeEffectToNBT(effect));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromNBT(NBTTagCompound compound) {
|
||||
if (compound.hasKey("effect")) {
|
||||
setEffect(SpellRegistry.instance().createEffectFromNBT(compound.getCompoundTag("effect")));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,7 +9,7 @@ import net.minecraft.util.math.RayTraceResult;
|
|||
import net.minecraftforge.event.entity.ProjectileImpactEvent;
|
||||
import net.minecraftforge.event.entity.item.ItemTossEvent;
|
||||
import net.minecraftforge.event.entity.living.LivingEntityUseItemEvent;
|
||||
import net.minecraftforge.event.entity.living.LivingEvent.LivingJumpEvent;
|
||||
import net.minecraftforge.event.entity.living.LivingEvent;
|
||||
import net.minecraftforge.event.entity.player.PlayerDropsEvent;
|
||||
import net.minecraftforge.event.entity.player.PlayerEvent;
|
||||
import net.minecraftforge.event.entity.player.PlayerFlyableFallEvent;
|
||||
|
@ -31,7 +31,12 @@ class Hooks {
|
|||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onPlayerJump(LivingJumpEvent event) {
|
||||
public static void onLivingUpdate(LivingEvent.LivingUpdateEvent event) {
|
||||
PlayerSpeciesList.instance().getEntity(event.getEntityLiving()).onUpdate();
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onPlayerJump(LivingEvent.LivingJumpEvent event) {
|
||||
if (event.getEntityLiving() instanceof EntityPlayer) {
|
||||
if (PlayerSpeciesList.instance().getPlayer((EntityPlayer)event.getEntityLiving()).getGravity().getGravitationConstant() < 0) {
|
||||
event.getEntityLiving().motionY = -event.getEntityLiving().motionY;
|
||||
|
|
|
@ -37,6 +37,7 @@ import net.minecraft.network.datasync.EntityDataManager;
|
|||
import net.minecraft.network.play.server.SPacketSetPassengers;
|
||||
import net.minecraft.potion.PotionEffect;
|
||||
import net.minecraft.stats.StatList;
|
||||
import net.minecraft.util.DamageSource;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
@ -310,6 +311,22 @@ class PlayerCapabilities implements IPlayer {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean subtractEnergyCost(double foodSubtract) {
|
||||
if (!entity.capabilities.isCreativeMode) {
|
||||
int food = (int)(entity.getFoodStats().getFoodLevel() - foodSubtract);
|
||||
|
||||
if (food < 0) {
|
||||
entity.getFoodStats().addStats(-entity.getFoodStats().getFoodLevel(), 0);
|
||||
entity.attackEntityFrom(DamageSource.MAGIC, -food/2);
|
||||
} else {
|
||||
entity.getFoodStats().addStats((int)-foodSubtract, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return entity.getHealth() > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stepOnCloud() {
|
||||
EntityPlayer player = getOwner();
|
||||
|
|
|
@ -7,8 +7,10 @@ import javax.annotation.Nullable;
|
|||
import com.minelittlepony.unicopia.Race;
|
||||
import com.minelittlepony.unicopia.UConfig;
|
||||
import com.minelittlepony.unicopia.forgebullshit.FBS;
|
||||
import com.minelittlepony.unicopia.spell.ICaster;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.item.EntityItem;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
|
||||
|
@ -65,6 +67,10 @@ public class PlayerSpeciesList {
|
|||
return new ItemCapabilities();
|
||||
}
|
||||
|
||||
if (entity instanceof EntityLivingBase) {
|
||||
return new EntityCapabilities((EntityLivingBase)entity);
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("entity");
|
||||
}
|
||||
|
||||
|
@ -82,6 +88,12 @@ public class PlayerSpeciesList {
|
|||
return getPlayer(IPlayer.getPlayerFromServer(playerId));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nullable
|
||||
public <T extends EntityLivingBase> ICaster<T> getCaster(T entity) {
|
||||
return (ICaster<T>)getEntity(entity);
|
||||
}
|
||||
|
||||
public <T extends Entity> IRaceContainer<T> getEntity(T entity) {
|
||||
return FBS.of(entity).getRaceContainer();
|
||||
}
|
||||
|
|
|
@ -10,38 +10,11 @@ import com.minelittlepony.util.shape.IShape;
|
|||
import com.minelittlepony.util.shape.Sphere;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.util.DamageSource;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public interface IPower<T extends IData> extends IKeyBind {
|
||||
|
||||
/**
|
||||
* Subtracts a given food amount from the player.
|
||||
* Harms the player if there is not enough hunger available.
|
||||
*/
|
||||
static boolean takeFromPlayer(EntityPlayer player, double foodSubtract) {
|
||||
if (!player.capabilities.isCreativeMode) {
|
||||
int food = (int)(player.getFoodStats().getFoodLevel() - foodSubtract);
|
||||
if (food < 0) {
|
||||
player.getFoodStats().addStats(-player.getFoodStats().getFoodLevel(), 0);
|
||||
player.attackEntityFrom(DamageSource.MAGIC, -food/2);
|
||||
} else {
|
||||
player.getFoodStats().addStats((int)-foodSubtract, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return player.getHealth() > 0;
|
||||
}
|
||||
|
||||
static double getPlayerEyeYPos(EntityPlayer player) {
|
||||
if (player.getEntityWorld().isRemote) {
|
||||
return player.posY + player.getEyeHeight() - player.getYOffset();
|
||||
}
|
||||
return player.posY + player.getEyeHeight() - 1;
|
||||
}
|
||||
|
||||
static void spawnParticles(int particleId, Entity entity, int count, int...args) {
|
||||
double halfDist = entity.getEyeHeight() / 1.5;
|
||||
double middle = entity.getEntityBoundingBox().minY + halfDist;
|
||||
|
|
|
@ -74,7 +74,7 @@ public class PowerGrow implements IPower<Location> {
|
|||
}
|
||||
|
||||
if (count > 0) {
|
||||
IPower.takeFromPlayer(player.getOwner(), count * 5);
|
||||
player.subtractEnergyCost(count * 5);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -166,13 +166,13 @@ public class PowerStomp implements IPower<PowerStomp.Data> {
|
|||
spawnParticleRing(player, i);
|
||||
}
|
||||
|
||||
IPower.takeFromPlayer(player, rad);
|
||||
iplayer.subtractEnergyCost(rad);
|
||||
} else if (data.hitType == 1) {
|
||||
|
||||
boolean harmed = player.getHealth() < player.getMaxHealth();
|
||||
|
||||
if (harmed && player.world.rand.nextInt(30) == 0) {
|
||||
IPower.takeFromPlayer(player, 3);
|
||||
iplayer.subtractEnergyCost(3);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -182,12 +182,12 @@ public class PowerStomp implements IPower<PowerStomp.Data> {
|
|||
UWorld.enqueueTask(w -> removeTree(w, data.pos()));
|
||||
}
|
||||
|
||||
IPower.takeFromPlayer(player, 3);
|
||||
iplayer.subtractEnergyCost(3);
|
||||
} else {
|
||||
int cost = dropApples(player.world, data.pos());
|
||||
|
||||
if (cost > 0) {
|
||||
IPower.takeFromPlayer(player, cost * 3);
|
||||
iplayer.subtractEnergyCost(cost * 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -128,7 +128,7 @@ public class PowerTeleport implements IPower<Location> {
|
|||
}
|
||||
|
||||
player.setPositionAndUpdate(data.x + (player.posX - Math.floor(player.posX)), data.y, data.z + (player.posZ - Math.floor(player.posZ)));
|
||||
IPower.takeFromPlayer(player, distance);
|
||||
iplayer.subtractEnergyCost(distance);
|
||||
|
||||
player.fallDistance /= distance;
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ import javax.annotation.Nullable;
|
|||
import com.google.common.collect.Streams;
|
||||
import com.minelittlepony.unicopia.Predicates;
|
||||
import com.minelittlepony.unicopia.entity.EntitySpell;
|
||||
import com.minelittlepony.unicopia.entity.IMagicals;
|
||||
import com.minelittlepony.unicopia.player.PlayerSpeciesList;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
|
@ -19,6 +20,9 @@ import net.minecraft.util.math.BlockPos;
|
|||
|
||||
public class CasterUtils {
|
||||
|
||||
/**
|
||||
* Finds all surrounding spells withing range from the given caster.
|
||||
*/
|
||||
public static Stream<ICaster<?>> findAllSpellsInRange(ICaster<?> source, double radius) {
|
||||
|
||||
BlockPos origin = source.getOrigin();
|
||||
|
@ -41,6 +45,9 @@ public class CasterUtils {
|
|||
.map(Optional::get);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all magically capabable entities in the world.
|
||||
*/
|
||||
static Stream<ICaster<?>> findAllSpells(ICaster<?> source) {
|
||||
return source.getWorld().getEntities(EntityLivingBase.class, e -> {
|
||||
return e instanceof ICaster || e instanceof EntityPlayer;
|
||||
|
@ -67,29 +74,50 @@ public class CasterUtils {
|
|||
.filter(e -> !e.getDead());
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the passed in entity is holding the named effect.
|
||||
* By holding that meant the effect must be attached to the caster associated with the entity.
|
||||
*/
|
||||
public static boolean isHoldingEffect(String effectName, Entity entity) {
|
||||
return Streams.stream(entity.getEquipmentAndArmor())
|
||||
.map(SpellRegistry::getKeyFromStack)
|
||||
.anyMatch(s -> s.equals(effectName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new caster at the position of the given entity.
|
||||
* First attempts to convert the passed entity into a caster.
|
||||
*/
|
||||
@Nonnull
|
||||
public static ICaster<?> near(@Nonnull Entity entity) {
|
||||
ICaster<?> result = toCasterRaw(entity);
|
||||
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
|
||||
EntitySpell caster = new EntitySpell(entity.world);
|
||||
caster.copyLocationAndAnglesFrom(entity);
|
||||
|
||||
return caster;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to convert the passed entity into a caster using all the known methods.
|
||||
*/
|
||||
public static Optional<ICaster<?>> toCaster(@Nullable Entity entity) {
|
||||
return Optional.ofNullable(toCasterRaw(entity));
|
||||
}
|
||||
|
||||
private static ICaster<?> toCasterRaw(Entity entity) {
|
||||
if (entity instanceof ICaster<?>) {
|
||||
return Optional.of((ICaster<?>)entity);
|
||||
return (ICaster<?>)entity;
|
||||
}
|
||||
|
||||
if (entity instanceof EntityPlayer) {
|
||||
return Optional.of(PlayerSpeciesList.instance().getPlayer((EntityPlayer)entity));
|
||||
if (entity instanceof EntityLivingBase && !(entity instanceof IMagicals)) {
|
||||
return PlayerSpeciesList.instance().getCaster((EntityLivingBase)entity);
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
package com.minelittlepony.unicopia.spell;
|
||||
|
||||
import com.minelittlepony.unicopia.player.IPlayer;
|
||||
|
||||
public interface IAttachedEffect extends IMagicEffect {
|
||||
/**
|
||||
* Called every tick when attached to a player.
|
||||
|
@ -9,7 +7,7 @@ public interface IAttachedEffect extends IMagicEffect {
|
|||
* @param source The entity we are currently attached to.
|
||||
* @return true to keep alive
|
||||
*/
|
||||
boolean updateOnPerson(IPlayer caster);
|
||||
boolean updateOnPerson(ICaster<?> caster);
|
||||
|
||||
/**
|
||||
* Called every tick when attached to a player. Used to apply particle effects.
|
||||
|
@ -17,5 +15,5 @@ public interface IAttachedEffect extends IMagicEffect {
|
|||
*
|
||||
* @param source The entity we are currently attached to.
|
||||
*/
|
||||
default void renderOnPerson(IPlayer source) {}
|
||||
default void renderOnPerson(ICaster<?> source) {}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import java.util.stream.Stream;
|
|||
import javax.annotation.Nullable;
|
||||
|
||||
import com.minelittlepony.unicopia.entity.EntitySpell;
|
||||
import com.minelittlepony.unicopia.entity.IMagicals;
|
||||
import com.minelittlepony.unicopia.player.IOwned;
|
||||
import com.minelittlepony.unicopia.power.IPower;
|
||||
import com.minelittlepony.util.shape.IShape;
|
||||
|
@ -15,28 +16,45 @@ import com.minelittlepony.util.vector.VecHelper;
|
|||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.util.DamageSource;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public interface ICaster<E extends EntityLivingBase> extends IOwned<E>, ILevelled, IAligned {
|
||||
/**
|
||||
* Interface for any magically capable entities that can cast and persist spells.
|
||||
*/
|
||||
public interface ICaster<E extends EntityLivingBase> extends IOwned<E>, ILevelled, IAligned, IMagicals {
|
||||
|
||||
void setEffect(@Nullable IMagicEffect effect);
|
||||
|
||||
/**
|
||||
* Gets the active effect for this caster.
|
||||
*/
|
||||
@Nullable
|
||||
default IMagicEffect getEffect(boolean update) {
|
||||
return getEffect(null, update);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the active effect for the matching given type.
|
||||
* Returns null if no such effect exists for this caster.
|
||||
*/
|
||||
@Nullable
|
||||
<T extends IMagicEffect> T getEffect(@Nullable Class<T> type, boolean update);
|
||||
|
||||
/**
|
||||
* Gets the active effect for this caster updating it if needed.
|
||||
*/
|
||||
@Nullable
|
||||
default IMagicEffect getEffect() {
|
||||
return getEffect(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this caster has an active effect attached to it.
|
||||
*/
|
||||
boolean hasEffect();
|
||||
|
||||
/**
|
||||
|
@ -81,6 +99,17 @@ public interface ICaster<E extends EntityLivingBase> extends IOwned<E>, ILevelle
|
|||
return getEntity().getPosition();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the center position where this caster is located.
|
||||
*/
|
||||
default Vec3d getOriginVector() {
|
||||
return getEntity().getPositionVector();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new caster at the given position.
|
||||
* This one is not altered, rather the method will return an entirely new caster with the same owner as this one.
|
||||
*/
|
||||
default ICaster<?> at(BlockPos newOrigin) {
|
||||
EntitySpell spell = new EntitySpell(getWorld());
|
||||
spell.setPosition(newOrigin.getX(), newOrigin.getY(), newOrigin.getZ());
|
||||
|
@ -89,10 +118,6 @@ public interface ICaster<E extends EntityLivingBase> extends IOwned<E>, ILevelle
|
|||
return spell;
|
||||
}
|
||||
|
||||
default Vec3d getOriginVector() {
|
||||
return getEntity().getPositionVector();
|
||||
}
|
||||
|
||||
default void spawnParticles(int particleId, int count, int...args) {
|
||||
IPower.spawnParticles(particleId, getEntity(), count, args);
|
||||
}
|
||||
|
@ -107,6 +132,12 @@ public interface ICaster<E extends EntityLivingBase> extends IOwned<E>, ILevelle
|
|||
}
|
||||
}
|
||||
|
||||
default boolean subtractEnergyCost(double amount) {
|
||||
getOwner().attackEntityFrom(DamageSource.MAGIC, (int)amount/2);
|
||||
|
||||
return getOwner().getHealth() > 0;
|
||||
}
|
||||
|
||||
default Stream<ICaster<?>> findAllSpells() {
|
||||
return CasterUtils.findAllSpells(this);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ import net.minecraft.util.EnumFacing;
|
|||
|
||||
/**
|
||||
* Represents an object with an action to perform when dispensed from a dispenser.
|
||||
*
|
||||
*/
|
||||
public interface IDispenceable extends IMagicEffect {
|
||||
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
package com.minelittlepony.unicopia.spell;
|
||||
|
||||
import com.minelittlepony.unicopia.entity.IMagicals;
|
||||
import com.minelittlepony.unicopia.init.UBlocks;
|
||||
import com.minelittlepony.unicopia.init.USounds;
|
||||
import com.minelittlepony.unicopia.player.IPlayer;
|
||||
import com.minelittlepony.unicopia.player.PlayerSpeciesList;
|
||||
import com.minelittlepony.util.WorldEvent;
|
||||
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.init.Items;
|
||||
|
@ -51,9 +52,14 @@ public class SpellChangelingTrap extends AbstractSpell implements ITossedEffect,
|
|||
return new ItemStack(Items.SLIME_BALL);
|
||||
}
|
||||
|
||||
private boolean checkStruggleCondition(ICaster<?> caster) {
|
||||
return !caster.getOrigin().equals(previousTrappedPosition)
|
||||
|| (!(caster.getOwner() instanceof EntityPlayer) && caster.getWorld().rand.nextInt(20) == 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateOnPerson(IPlayer caster) {
|
||||
EntityPlayer entity = caster.getOwner();
|
||||
public boolean updateOnPerson(ICaster<?> caster) {
|
||||
EntityLivingBase entity = caster.getOwner();
|
||||
|
||||
if (entity.motionY > 0) {
|
||||
entity.playSound(SoundEvents.BLOCK_SLIME_HIT, 1, 1);
|
||||
|
@ -67,15 +73,13 @@ public class SpellChangelingTrap extends AbstractSpell implements ITossedEffect,
|
|||
setDirty(true);
|
||||
}
|
||||
|
||||
if (!caster.getWorld().isRemote) {
|
||||
if (!origin.equals(previousTrappedPosition)) {
|
||||
if (!caster.getWorld().isRemote && checkStruggleCondition(caster)) {
|
||||
previousTrappedPosition = origin;
|
||||
struggleCounter--;
|
||||
WorldEvent.DESTROY_BLOCK.play(caster.getWorld(), origin, Blocks.SLIME_BLOCK.getDefaultState());
|
||||
|
||||
setDirty(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (caster.getWorld().isAirBlock(origin) || caster.getWorld().getBlockState(origin).getBlock().isReplaceable(caster.getWorld(), origin)) {
|
||||
caster.getWorld().setBlockState(origin, UBlocks.slime_layer.getDefaultState());
|
||||
|
@ -97,7 +101,10 @@ public class SpellChangelingTrap extends AbstractSpell implements ITossedEffect,
|
|||
entity.hurtTime = 2;
|
||||
entity.collidedHorizontally = true;
|
||||
entity.collided = true;
|
||||
entity.capabilities.isFlying = false;
|
||||
|
||||
if (entity instanceof EntityPlayer) {
|
||||
((EntityPlayer)entity).capabilities.isFlying = false;
|
||||
}
|
||||
|
||||
PotionEffect SLIME_REGEN = new PotionEffect(MobEffects.REGENERATION, 0);
|
||||
|
||||
|
@ -126,7 +133,7 @@ public class SpellChangelingTrap extends AbstractSpell implements ITossedEffect,
|
|||
}
|
||||
|
||||
@Override
|
||||
public void renderOnPerson(IPlayer source) {
|
||||
public void renderOnPerson(ICaster<?> source) {
|
||||
render(source);
|
||||
}
|
||||
|
||||
|
@ -140,7 +147,7 @@ public class SpellChangelingTrap extends AbstractSpell implements ITossedEffect,
|
|||
setDirty(true);
|
||||
}
|
||||
|
||||
protected void entrap(IPlayer e) {
|
||||
protected void entrap(ICaster<?> e) {
|
||||
|
||||
SpellChangelingTrap existing = e.getEffect(SpellChangelingTrap.class, true);
|
||||
|
||||
|
@ -155,8 +162,8 @@ public class SpellChangelingTrap extends AbstractSpell implements ITossedEffect,
|
|||
public void onImpact(ICaster<?> caster, BlockPos pos, IBlockState state) {
|
||||
if (caster.isLocal()) {
|
||||
caster.findAllEntitiesInRange(5)
|
||||
.filter(e -> e instanceof EntityPlayer)
|
||||
.map(e -> PlayerSpeciesList.instance().getPlayer((EntityPlayer)e))
|
||||
.filter(e -> !(e instanceof IMagicals) && e instanceof EntityLivingBase)
|
||||
.map(e -> PlayerSpeciesList.instance().getCaster((EntityLivingBase)e))
|
||||
.forEach(this::entrap);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -146,8 +146,6 @@ public class SpellDisguise extends AbstractSpell implements IAttachedEffect, ISu
|
|||
entity.setUniqueId(UUID.randomUUID());
|
||||
entity.extinguish();
|
||||
|
||||
PlayerSpeciesList.instance().getPlayer((EntityPlayer)entity).setEffect(null);
|
||||
|
||||
onEntityLoaded(source);
|
||||
}
|
||||
|
||||
|
@ -179,6 +177,8 @@ public class SpellDisguise extends AbstractSpell implements IAttachedEffect, ISu
|
|||
return;
|
||||
}
|
||||
|
||||
CasterUtils.toCaster(entity).ifPresent(c -> c.setEffect(null));
|
||||
|
||||
if (source.getWorld().isRemote) {
|
||||
source.getWorld().spawnEntity(entity);
|
||||
}
|
||||
|
@ -289,7 +289,7 @@ public class SpellDisguise extends AbstractSpell implements IAttachedEffect, ISu
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean updateOnPerson(IPlayer caster) {
|
||||
public boolean updateOnPerson(ICaster<?> caster) {
|
||||
return update(caster);
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@ import com.minelittlepony.unicopia.particle.ParticleConnection;
|
|||
import com.minelittlepony.unicopia.particle.Particles;
|
||||
import com.minelittlepony.unicopia.player.IPlayer;
|
||||
import com.minelittlepony.unicopia.player.PlayerSpeciesList;
|
||||
import com.minelittlepony.unicopia.power.IPower;
|
||||
import com.minelittlepony.util.ProjectileUtil;
|
||||
import com.minelittlepony.util.shape.Sphere;
|
||||
|
||||
|
@ -39,7 +38,7 @@ public class SpellShield extends AbstractSpell.RangedAreaSpell implements IAttac
|
|||
}
|
||||
|
||||
@Override
|
||||
public void renderOnPerson(IPlayer source) {
|
||||
public void renderOnPerson(ICaster<?> source) {
|
||||
render(source);
|
||||
}
|
||||
|
||||
|
@ -57,7 +56,7 @@ public class SpellShield extends AbstractSpell.RangedAreaSpell implements IAttac
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean updateOnPerson(IPlayer source) {
|
||||
public boolean updateOnPerson(ICaster<?> source) {
|
||||
int costMultiplier = applyEntities(source);
|
||||
if (costMultiplier > 0) {
|
||||
if (source.getOwner().ticksExisted % 20 == 0) {
|
||||
|
@ -66,7 +65,7 @@ public class SpellShield extends AbstractSpell.RangedAreaSpell implements IAttac
|
|||
cost *= costMultiplier / 5F;
|
||||
System.out.println("Taking " + cost);
|
||||
|
||||
if (!IPower.takeFromPlayer(source.getOwner(), cost)) {
|
||||
if (!source.subtractEnergyCost(cost)) {
|
||||
setDead();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue