Added a transformation spell

This commit is contained in:
Sollace 2021-08-25 00:32:39 +02:00
parent 465d86cffd
commit c3e854fdd1
6 changed files with 151 additions and 13 deletions

View file

@ -4,6 +4,7 @@ import com.minelittlepony.unicopia.item.toxin.Toxics;
import net.fabricmc.fabric.api.tag.TagRegistry;
import net.minecraft.block.Block;
import net.minecraft.entity.EntityType;
import net.minecraft.item.Item;
import net.minecraft.tag.Tag;
import net.minecraft.util.Identifier;
@ -24,6 +25,8 @@ public interface UTags {
Tag<Block> CRYSTAL_HEART_BASE = block("crystal_heart_base");
Tag<Block> CRYSTAL_HEART_ORNAMENT = block("crystal_heart_ornament");
Tag<EntityType<?>> TRANSFORMABLE_ENTITIES = entity("transformable");
static Tag<Item> item(String name) {
return TagRegistry.item(new Identifier("unicopia", name));
}
@ -32,6 +35,10 @@ public interface UTags {
return TagRegistry.block(new Identifier("unicopia", name));
}
static Tag<EntityType<?>> entity(String name) {
return TagRegistry.entityType(new Identifier("unicopia", name));
}
static void bootstrap() {
Toxics.bootstrap();
}

View file

@ -44,6 +44,7 @@ public final class SpellType<T extends Spell> implements Affine, SpellPredicate<
public static final SpellType<RevealingSpell> REVEALING = register("reveal", Affinity.GOOD, 0x5CE81F, true, RevealingSpell::new);
public static final SpellType<JoustingSpell> JOUSTING = register("joust", Affinity.GOOD, 0xBDBDF9, false, JoustingSpell::new);
public static final SpellType<AwkwardSpell> AWKWARD = register("awkward", Affinity.GOOD, 0xE1239C, true, AwkwardSpell::new);
public static final SpellType<TransformationSpell> TRANSFORMATION = register("transformation", Affinity.NEUTRAL, 0x3A59AA, true, TransformationSpell::new);
private final Identifier id;
private final Affinity affinity;

View file

@ -0,0 +1,72 @@
package com.minelittlepony.unicopia.ability.magic.spell;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Optional;
import java.util.Random;
import java.util.Set;
import com.minelittlepony.unicopia.UTags;
import com.minelittlepony.unicopia.ability.magic.Thrown;
import com.minelittlepony.unicopia.entity.UEntities;
import com.minelittlepony.unicopia.particle.ParticleUtils;
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.SpawnGroup;
import net.minecraft.entity.mob.MobEntity;
import net.minecraft.particle.ParticleTypes;
import net.minecraft.sound.SoundEvents;
import net.minecraft.util.Util;
public class TransformationSpell extends AbstractSpell implements Thrown {
protected TransformationSpell(SpellType<?> type) {
super(type);
}
@Override
public boolean onThrownTick(MagicProjectileEntity source) {
return true;
}
@Override
public void onImpact(MagicProjectileEntity projectile, Entity entity) {
if (projectile.world.isClient) {
return;
}
pickType(entity.getType(), entity.world.random).flatMap(type -> convert(entity, type)).ifPresentOrElse(e -> {
entity.playSound(SoundEvents.ENTITY_ITEM_PICKUP, 1, 1);
}, () -> {
ParticleUtils.spawnParticles(ParticleTypes.SMOKE, entity, 20);
entity.playSound(SoundEvents.BLOCK_NOTE_BLOCK_DIDGERIDOO, 1, 1);
});
}
private Optional<? extends MobEntity> convert(Entity entity, EntityType<? extends MobEntity> type) {
if (entity instanceof MobEntity) {
MobEntity mob = (MobEntity)entity;
try {
return Optional.ofNullable(mob.convertTo(type, true));
} catch (Exception e) {
return Optional.ofNullable(mob.convertTo(UEntities.BUTTERFLY, true));
}
}
return Optional.empty();
}
@SuppressWarnings("unchecked")
private <T extends MobEntity> Optional<EntityType<T>> pickType(EntityType<?> except, Random random) {
Set<EntityType<?>> options = new HashSet<>(UTags.TRANSFORMABLE_ENTITIES.values());
if (except.getSpawnGroup() == SpawnGroup.MONSTER) {
options.removeIf(t -> t.getSpawnGroup() == SpawnGroup.MONSTER);
} else {
options.remove(except);
}
if (options.size() <= 1) {
return options.stream().findFirst().map(t -> (EntityType<T>)t);
}
return Optional.ofNullable((EntityType<T>)Util.getRandom(new ArrayList<>(options), random));
}
}

View file

@ -1,5 +1,7 @@
package com.minelittlepony.unicopia.projectile;
import java.util.function.Consumer;
import com.minelittlepony.unicopia.Affinity;
import com.minelittlepony.unicopia.ability.magic.Affine;
import com.minelittlepony.unicopia.ability.magic.Caster;
@ -145,7 +147,7 @@ public class MagicProjectileEntity extends ThrownItemEntity implements Caster<Li
public void tick() {
if (!world.isClient()) {
if (Math.abs(getVelocity().x) < 0.01 && Math.abs(getVelocity().x) < 0.01 && Math.abs(getVelocity().y) < 0.01) {
remove(RemovalReason.DISCARDED);
discard();
}
}
@ -161,7 +163,7 @@ public class MagicProjectileEntity extends ThrownItemEntity implements Caster<Li
}
if (!getSpellSlot().get(SpellPredicate.IS_THROWN, true).filter(spell -> spell.onThrownTick(this)).isPresent()) {
remove(RemovalReason.DISCARDED);
discard();
}
}
@ -229,25 +231,21 @@ public class MagicProjectileEntity extends ThrownItemEntity implements Caster<Li
@Override
protected void onCollision(HitResult result) {
if (!isRemoved()) {
remove(RemovalReason.DISCARDED);
discard();
super.onCollision(result);
if (!world.isClient()) {
world.sendEntityStatus(this, (byte)3);
remove(RemovalReason.DISCARDED);
discard();
}
}
}
@Override
protected void onBlockHit(BlockHitResult hit) {
getSpellSlot().get(SpellPredicate.IS_THROWN, true).ifPresent(effect -> {
effect.onImpact(this, hit.getBlockPos(), world.getBlockState(hit.getBlockPos()));
});
super.onBlockHit(hit);
if (getItem().getItem() instanceof ProjectileDelegate) {
((ProjectileDelegate)getItem().getItem()).onImpact(this, hit.getBlockPos(), world.getBlockState(hit.getBlockPos()));
}
forEachDelegates(effect -> effect.onImpact(this, hit.getBlockPos(), world.getBlockState(hit.getBlockPos())));
}
@Override
@ -259,11 +257,20 @@ public class MagicProjectileEntity extends ThrownItemEntity implements Caster<Li
}
if (entity != null) {
entity.damage(DamageSource.thrownProjectile(this, getOwner()), getThrowDamage());
}
float damage = getThrowDamage();
if (damage > 0) {
entity.damage(DamageSource.thrownProjectile(this, getOwner()), getThrowDamage());
}
forEachDelegates(effect -> effect.onImpact(this, entity));
}
}
protected void forEachDelegates(Consumer<ProjectileDelegate> consumer) {
getSpellSlot().get(SpellPredicate.IS_THROWN, true).ifPresent(consumer);
if (getItem().getItem() instanceof ProjectileDelegate) {
((ProjectileDelegate)getItem().getItem()).onImpact(this, entity);
consumer.accept(((ProjectileDelegate)getItem().getItem()));
}
}

View file

@ -156,6 +156,9 @@
"spell.unicopia.awkward": "Unstable",
"spell.unicopia.awkward.lore": "Chaos I",
"spell.unicopia.transformation": "Transformation",
"spell.unicopia.transformation.lore": "Chaos II",
"toxicity.safe.name": "Safe",
"toxicity.mild.name": "Mildly Toxic",

View file

@ -0,0 +1,48 @@
{
"replace": false,
"values": [
"minecraft:skeleton",
"minecraft:wither_skeleton",
"minecraft:zombie",
"minecraft:drowned",
"minecraft:husk",
"minecraft:creeper",
"minecraft:villager",
"minecraft:wandering_trader",
"minecraft:wither_skeleton",
"minecraft:witch",
"minecraft:turtle",
"minecraft:zombie_villager",
"minecraft:blaze",
"minecraft:sheep",
"minecraft:salmon",
"minecraft:rabbit",
"minecraft:pufferfish",
"minecraft:pillager",
"minecraft:polar_bear",
"minecraft:pig",
"minecraft:llama",
"minecraft:goat",
"minecraft:illusioner",
"minecraft:donkey",
"minecraft:cow",
"minecraft:cod",
"minecraft:mooshroom",
"minecraft:panda",
"minecraft:parrot",
"minecraft:chicken",
"minecraft:spider",
"minecraft:cave_spider",
"minecraft:mule",
"minecraft:magma_cube",
"minecraft:cat",
"minecraft:ocelot",
"minecraft:bee",
"minecraft:squid",
"minecraft:glow_squid",
"minecraft:fox",
"minecraft:wolf",
"minecraft:horse",
"unicopia:butterfly"
]
}