mirror of
https://github.com/Sollace/Unicopia.git
synced 2024-11-30 16:28:00 +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.SoundType;
|
||||||
import net.minecraft.block.state.IBlockState;
|
import net.minecraft.block.state.IBlockState;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.EntityLiving;
|
import net.minecraft.entity.EntityCreature;
|
||||||
import net.minecraft.entity.EntityLivingBase;
|
import net.minecraft.entity.EntityLivingBase;
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
import net.minecraft.init.SoundEvents;
|
import net.minecraft.init.SoundEvents;
|
||||||
|
@ -35,7 +35,7 @@ import net.minecraft.util.SoundCategory;
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
import net.minecraft.world.World;
|
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;
|
private EntityLivingBase owner = null;
|
||||||
|
|
||||||
|
|
|
@ -15,8 +15,6 @@ import com.minelittlepony.util.render.Color;
|
||||||
|
|
||||||
public class ParticleSphere extends Particle implements IAttachableParticle {
|
public class ParticleSphere extends Particle implements IAttachableParticle {
|
||||||
|
|
||||||
private final float baseAlpha;
|
|
||||||
|
|
||||||
protected int tint;
|
protected int tint;
|
||||||
protected float alpha;
|
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) {
|
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(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) {
|
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.radius = radius;
|
||||||
this.tint = tint;
|
this.tint = tint;
|
||||||
this.alpha = alpha;
|
this.alpha = alpha;
|
||||||
this.baseAlpha = alpha;
|
|
||||||
|
|
||||||
this.setMaxAge(50000);
|
setMaxAge(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -48,29 +49,34 @@ public class ParticleSphere extends Particle implements IAttachableParticle {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void attachTo(ICaster<?> caster) {
|
public void attachTo(ICaster<?> caster) {
|
||||||
|
setMaxAge(50000);
|
||||||
this.caster = caster;
|
this.caster = caster;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onUpdate() {
|
public void onUpdate() {
|
||||||
super.onUpdate();
|
super.onUpdate();
|
||||||
|
|
||||||
alpha = Math.min(1F, 1 - (float)particleAge/particleMaxAge) * baseAlpha;
|
if (caster != null) {
|
||||||
|
if (!caster.hasEffect() || caster.getEffect().getDead() || caster.getEntity().isDead) {
|
||||||
if (caster == null || !caster.hasEffect() || caster.getEffect().getDead() || caster.getEntity().isDead) {
|
|
||||||
setExpired();
|
|
||||||
} else {
|
|
||||||
Entity e = caster.getEntity();
|
|
||||||
|
|
||||||
if (!caster.getWorld().loadedEntityList.contains(caster.getEntity())) {
|
|
||||||
setExpired();
|
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) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import java.util.stream.Stream;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.google.common.collect.Streams;
|
||||||
import com.minelittlepony.unicopia.Predicates;
|
import com.minelittlepony.unicopia.Predicates;
|
||||||
import com.minelittlepony.unicopia.player.PlayerSpeciesList;
|
import com.minelittlepony.unicopia.player.PlayerSpeciesList;
|
||||||
|
|
||||||
|
@ -54,6 +55,12 @@ public class CasterUtils {
|
||||||
.filter(e -> !e.getDead());
|
.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) {
|
public static Optional<ICaster<?>> toCaster(@Nullable Entity entity) {
|
||||||
|
|
||||||
if (entity instanceof ICaster<?>) {
|
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
|
@Nullable
|
||||||
private IMagicEffect piggyBackSpell;
|
private IMagicEffect piggyBackSpell;
|
||||||
|
|
||||||
private boolean firstUpdate = true;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "drake";
|
return "drake";
|
||||||
|
@ -26,7 +24,7 @@ public class SpellDrake extends AbstractSpell {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SpellAffinity getAffinity() {
|
public SpellAffinity getAffinity() {
|
||||||
return SpellAffinity.NEUTRAL;
|
return SpellAffinity.GOOD;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -53,23 +51,21 @@ public class SpellDrake extends AbstractSpell {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean update(ICaster<?> source) {
|
public void onPlaced(ICaster<?> caster) {
|
||||||
|
if (caster.getEntity() instanceof EntitySpell) {
|
||||||
|
EntitySpell living = (EntitySpell)caster.getEntity();
|
||||||
|
|
||||||
if (firstUpdate) {
|
((PathNavigateGround)living.getNavigator()).setCanSwim(false);
|
||||||
firstUpdate = 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) {
|
living.setPosition(living.posX, living.posY, living.posZ);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean update(ICaster<?> source) {
|
||||||
if (piggyBackSpell == null) {
|
if (piggyBackSpell == null) {
|
||||||
AxisAlignedBB bb = EFFECT_BOUNDS.offset(source.getOriginVector());
|
AxisAlignedBB bb = EFFECT_BOUNDS.offset(source.getOriginVector());
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,7 @@ public class SpellRegistry {
|
||||||
registerSpell(SpellInferno::new);
|
registerSpell(SpellInferno::new);
|
||||||
registerSpell(SpellDrake::new);
|
registerSpell(SpellDrake::new);
|
||||||
registerSpell(SpellReveal::new);
|
registerSpell(SpellReveal::new);
|
||||||
|
registerSpell(SpellDarkness::new);
|
||||||
registerSpell(GenericSpell.factory("light", 0xF7FACB, SpellAffinity.GOOD));
|
registerSpell(GenericSpell.factory("light", 0xF7FACB, SpellAffinity.GOOD));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,11 +63,17 @@ spell.ice.name=Frost
|
||||||
spell.ice.tagline=Ice I
|
spell.ice.tagline=Ice I
|
||||||
|
|
||||||
spell.drake.name=Assistance
|
spell.drake.name=Assistance
|
||||||
spell.drake.tagline=Helpfulness I
|
spell.drake.tagline=Golomancy I
|
||||||
|
|
||||||
curse.shield.name=Repulsion
|
curse.shield.name=Repulsion
|
||||||
curse.shield.tagline=Hostility I
|
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.name=Awkwardness
|
||||||
curse.awkward.tagline=*Derp*
|
curse.awkward.tagline=*Derp*
|
||||||
|
|
||||||
|
@ -77,9 +83,6 @@ curse.vortex.tagline=Torture I
|
||||||
curse.necromancy.name=Necromancy
|
curse.necromancy.name=Necromancy
|
||||||
curse.necromancy.tagline=Resurrection I
|
curse.necromancy.tagline=Resurrection I
|
||||||
|
|
||||||
curse.drake.name=Assistance
|
|
||||||
curse.drake.tagline=Unhelpfulness I
|
|
||||||
|
|
||||||
curse.inferno.name=Inferno
|
curse.inferno.name=Inferno
|
||||||
curse.inferno.tagline=Fire II
|
curse.inferno.tagline=Fire II
|
||||||
|
|
||||||
|
@ -218,6 +221,7 @@ unicopia.power.disguise=Secondary Changeling ability
|
||||||
|
|
||||||
unicopia.gui.title.bagofholding=Bag of Holding
|
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=%1$s was drained of all life
|
||||||
death.attack.feed.player=%1$s died to feed %2$s
|
death.attack.feed.player=%1$s died to feed %2$s
|
||||||
death.attack.cold=%1$s died of frost bite
|
death.attack.cold=%1$s died of frost bite
|
||||||
|
|
Loading…
Reference in a new issue