Added the cursed gem of darkness

This commit is contained in:
Sollace 2019-02-14 22:59:11 +02:00
parent 6b66a09414
commit 5e3316e232
7 changed files with 182 additions and 37 deletions

View file

@ -17,7 +17,7 @@ import com.minelittlepony.unicopia.spell.SpellRegistry;
import net.minecraft.block.SoundType;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityCreature;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.SoundEvents;
@ -35,7 +35,7 @@ import net.minecraft.util.SoundCategory;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
public class EntitySpell extends EntityLiving implements IMagicals, ICaster<EntityLivingBase>, IInAnimate {
public class EntitySpell extends EntityCreature implements IMagicals, ICaster<EntityLivingBase>, IInAnimate {
private EntityLivingBase owner = null;

View file

@ -15,8 +15,6 @@ import com.minelittlepony.util.render.Color;
public class ParticleSphere extends Particle implements IAttachableParticle {
private final float baseAlpha;
protected int tint;
protected float alpha;
@ -28,6 +26,10 @@ public class ParticleSphere extends Particle implements IAttachableParticle {
public ParticleSphere(int id, World w, double x, double y, double z, double vX, double vY, double vZ, int... args) {
this(w, x, y, z, args[0], args[1], args[2]/255F);
this.motionX = vX;
this.motionY = vY;
this.motionZ = vZ;
}
public ParticleSphere(World w, double x, double y, double z, int radius, int tint, float alpha) {
@ -36,9 +38,8 @@ public class ParticleSphere extends Particle implements IAttachableParticle {
this.radius = radius;
this.tint = tint;
this.alpha = alpha;
this.baseAlpha = alpha;
this.setMaxAge(50000);
setMaxAge(10);
}
@Override
@ -48,29 +49,34 @@ public class ParticleSphere extends Particle implements IAttachableParticle {
@Override
public void attachTo(ICaster<?> caster) {
setMaxAge(50000);
this.caster = caster;
}
public void onUpdate() {
super.onUpdate();
alpha = Math.min(1F, 1 - (float)particleAge/particleMaxAge) * baseAlpha;
if (caster == null || !caster.hasEffect() || caster.getEffect().getDead() || caster.getEntity().isDead) {
setExpired();
} else {
Entity e = caster.getEntity();
if (!caster.getWorld().loadedEntityList.contains(caster.getEntity())) {
if (caster != null) {
if (!caster.hasEffect() || caster.getEffect().getDead() || caster.getEntity().isDead) {
setExpired();
}
} else {
Entity e = caster.getEntity();
setPosition(e.posX, e.posY, e.posZ);
if (!caster.getWorld().loadedEntityList.contains(caster.getEntity())) {
setExpired();
}
setPosition(e.posX, e.posY, e.posZ);
}
} else {
if (this.rand.nextInt(10000) == 0) {
this.radius--;
}
}
}
public void renderParticle(BufferBuilder buffer, Entity viewer, float partialTicks, float x, float z, float yz, float xy, float xz) {
if (alpha <= 0) {
if (alpha <= 0 || radius <= 0) {
return;
}

View file

@ -5,6 +5,7 @@ import java.util.stream.Stream;
import javax.annotation.Nullable;
import com.google.common.collect.Streams;
import com.minelittlepony.unicopia.Predicates;
import com.minelittlepony.unicopia.player.PlayerSpeciesList;
@ -54,6 +55,12 @@ public class CasterUtils {
.filter(e -> !e.getDead());
}
public static boolean isHoldingEffect(String effectName, Entity entity) {
return Streams.stream(entity.getEquipmentAndArmor())
.map(SpellRegistry::getKeyFromStack)
.anyMatch(s -> s.equals(effectName));
}
public static Optional<ICaster<?>> toCaster(@Nullable Entity entity) {
if (entity instanceof ICaster<?>) {

View file

@ -0,0 +1,131 @@
package com.minelittlepony.unicopia.spell;
import java.util.Random;
import com.minelittlepony.unicopia.UParticles;
import com.minelittlepony.unicopia.entity.EntitySpell;
import com.minelittlepony.unicopia.particle.Particles;
import com.minelittlepony.util.MagicalDamageSource;
import com.minelittlepony.util.shape.Sphere;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.ai.EntityAIAvoidEntity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.MobEffects;
import net.minecraft.init.SoundEvents;
import net.minecraft.potion.PotionEffect;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
public class SpellDarkness extends AbstractSpell.RangedAreaSpell {
final SoundEvent[] scarySounds = new SoundEvent[] {
SoundEvents.AMBIENT_CAVE,
SoundEvents.ENTITY_GHAST_SCREAM,
SoundEvents.ENTITY_ZOMBIE_AMBIENT,
SoundEvents.ENTITY_GHAST_AMBIENT,
SoundEvents.ENTITY_SKELETON_AMBIENT,
SoundEvents.ENTITY_SKELETON_SHOOT,
SoundEvents.ENTITY_ENDERDRAGON_GROWL,
SoundEvents.ENTITY_ENDERMEN_SCREAM,
SoundEvents.ENTITY_ZOMBIE_VILLAGER_AMBIENT
};
@Override
public String getName() {
return "darkness";
}
@Override
public int getTint() {
return 0x000000;
}
@Override
public boolean allowAI() {
return true;
}
@Override
public void onPlaced(ICaster<?> caster) {
if (caster.getEntity() instanceof EntitySpell) {
EntitySpell living = (EntitySpell)caster.getEntity();
living.tasks.addTask(1, new EntityAIAvoidEntity<>(living, EntityPlayer.class, 3, 4, 4));
living.height = 1.8F;
living.setPosition(living.posX, living.posY, living.posZ);
}
}
@Override
public boolean update(ICaster<?> source) {
int radius = 7 + (source.getCurrentLevel() * 3);
if (source.getWorld().rand.nextInt(15) == 0) {
source.getWorld().playSound(null, source.getOrigin(), getScarySoundEffect(source.getWorld().rand), SoundCategory.AMBIENT,
0.2F + source.getWorld().rand.nextFloat(), 0.3F);
}
source.findAllEntitiesInRange(radius * 1.5F)
.filter(e -> e instanceof EntityLivingBase)
.map(EntityLivingBase.class::cast)
.forEach(e -> applyDarkness(source, e));
return false;
}
protected void applyDarkness(ICaster<?> source, EntityLivingBase entity) {
if (!CasterUtils.isHoldingEffect("light", entity)) {
entity.addPotionEffect(new PotionEffect(MobEffects.BLINDNESS, 100, 3));
Vec3d origin = source.getOriginVector();
Vec3d to = entity.getPositionVector();
double distance = origin.distanceTo(entity.getPositionVector());
if (entity.world.rand.nextInt(30) == 0) {
double appliedForce = distance / 10 + entity.world.rand.nextInt(3);
Vec3d force = origin.subtract(to).normalize().scale(appliedForce);
entity.addVelocity(force.x, force.y, force.z);
}
if (distance < 3 && entity.world.rand.nextInt(30) == 0) {
entity.attackEntityFrom(MagicalDamageSource.create("darkness"), 3);
}
} else {
if (entity.isPotionActive(MobEffects.BLINDNESS)) {
entity.removeActivePotionEffect(MobEffects.BLINDNESS);
}
}
}
protected SoundEvent getScarySoundEffect(Random rand) {
return scarySounds[rand.nextInt(scarySounds.length)];
}
@Override
public void render(ICaster<?> source) {
int radius = 7 + (source.getCurrentLevel() * 3);
source.spawnParticles(new Sphere(false, radius), radius * 6, pos -> {
if (!source.getWorld().isAirBlock(new BlockPos(pos).down())) {
int size = source.getWorld().rand.nextInt(4);
if (size > 0) {
double vX = (source.getWorld().rand.nextFloat() - 0.5) * 2;
double vZ = (source.getWorld().rand.nextFloat() - 0.5) * 2;
Particles.instance().spawnParticle(UParticles.SPHERE, false, pos, vX, 0, vZ, size, getTint(), 100);
}
}
});
}
@Override
public SpellAffinity getAffinity() {
return SpellAffinity.BAD;
}
}

View file

@ -17,8 +17,6 @@ public class SpellDrake extends AbstractSpell {
@Nullable
private IMagicEffect piggyBackSpell;
private boolean firstUpdate = true;
@Override
public String getName() {
return "drake";
@ -26,7 +24,7 @@ public class SpellDrake extends AbstractSpell {
@Override
public SpellAffinity getAffinity() {
return SpellAffinity.NEUTRAL;
return SpellAffinity.GOOD;
}
@Override
@ -53,23 +51,21 @@ public class SpellDrake extends AbstractSpell {
}
@Override
public boolean update(ICaster<?> source) {
public void onPlaced(ICaster<?> caster) {
if (caster.getEntity() instanceof EntitySpell) {
EntitySpell living = (EntitySpell)caster.getEntity();
if (firstUpdate) {
firstUpdate = false;
((PathNavigateGround)living.getNavigator()).setCanSwim(false);
living.tasks.addTask(1, new EntityAISwimming(living));
living.tasks.addTask(2, new EntityAIFollowCaster<>(caster, 1, 4, 70));
living.height = 1.8F;
if (source.getEntity() instanceof EntitySpell) {
EntitySpell living = (EntitySpell)source.getEntity();
((PathNavigateGround)living.getNavigator()).setCanSwim(false);
living.tasks.addTask(1, new EntityAISwimming(living));
living.tasks.addTask(2, new EntityAIFollowCaster<>(source, 1, 4, 70));
living.height = 1.8F;
living.setPosition(living.posX, living.posY, living.posZ);
}
living.setPosition(living.posX, living.posY, living.posZ);
}
}
@Override
public boolean update(ICaster<?> source) {
if (piggyBackSpell == null) {
AxisAlignedBB bb = EFFECT_BOUNDS.offset(source.getOriginVector());

View file

@ -43,6 +43,7 @@ public class SpellRegistry {
registerSpell(SpellInferno::new);
registerSpell(SpellDrake::new);
registerSpell(SpellReveal::new);
registerSpell(SpellDarkness::new);
registerSpell(GenericSpell.factory("light", 0xF7FACB, SpellAffinity.GOOD));
}

View file

@ -63,11 +63,17 @@ spell.ice.name=Frost
spell.ice.tagline=Ice I
spell.drake.name=Assistance
spell.drake.tagline=Helpfulness I
spell.drake.tagline=Golomancy I
curse.shield.name=Repulsion
curse.shield.tagline=Hostility I
curse.darkness.name=Darkness
curse.darkness.tagline=Golomancy I/Resurrection II
curse.harm.name=Hurting
curse.harm.tagline=Hostility II
curse.awkward.name=Awkwardness
curse.awkward.tagline=*Derp*
@ -77,9 +83,6 @@ curse.vortex.tagline=Torture I
curse.necromancy.name=Necromancy
curse.necromancy.tagline=Resurrection I
curse.drake.name=Assistance
curse.drake.tagline=Unhelpfulness I
curse.inferno.name=Inferno
curse.inferno.tagline=Fire II
@ -218,6 +221,7 @@ unicopia.power.disguise=Secondary Changeling ability
unicopia.gui.title.bagofholding=Bag of Holding
death.attack.darkness=%1$s went missing
death.attack.feed=%1$s was drained of all life
death.attack.feed.player=%1$s died to feed %2$s
death.attack.cold=%1$s died of frost bite