mirror of
https://github.com/Sollace/Unicopia.git
synced 2024-11-27 23:27:59 +01:00
Added the cursed gem of darkness
This commit is contained in:
parent
6b66a09414
commit
5e3316e232
7 changed files with 182 additions and 37 deletions
|
@ -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;
|
||||
|
||||
|
|
|
@ -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,15 +49,15 @@ 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) {
|
||||
if (caster != null) {
|
||||
if (!caster.hasEffect() || caster.getEffect().getDead() || caster.getEntity().isDead) {
|
||||
setExpired();
|
||||
} else {
|
||||
Entity e = caster.getEntity();
|
||||
|
@ -67,10 +68,15 @@ public class ParticleSphere extends Particle implements IAttachableParticle {
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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<?>) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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) {
|
||||
|
||||
if (firstUpdate) {
|
||||
firstUpdate = false;
|
||||
|
||||
if (source.getEntity() instanceof EntitySpell) {
|
||||
EntitySpell living = (EntitySpell)source.getEntity();
|
||||
public void onPlaced(ICaster<?> caster) {
|
||||
if (caster.getEntity() instanceof EntitySpell) {
|
||||
EntitySpell living = (EntitySpell)caster.getEntity();
|
||||
|
||||
((PathNavigateGround)living.getNavigator()).setCanSwim(false);
|
||||
living.tasks.addTask(1, new EntityAISwimming(living));
|
||||
living.tasks.addTask(2, new EntityAIFollowCaster<>(source, 1, 4, 70));
|
||||
living.tasks.addTask(2, new EntityAIFollowCaster<>(caster, 1, 4, 70));
|
||||
living.height = 1.8F;
|
||||
|
||||
living.setPosition(living.posX, living.posY, living.posZ);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean update(ICaster<?> source) {
|
||||
if (piggyBackSpell == null) {
|
||||
AxisAlignedBB bb = EFFECT_BOUNDS.offset(source.getOriginVector());
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue