Implement traits to modify spell behaviours

This commit is contained in:
Sollace 2021-11-13 19:31:45 +02:00
parent 78a33deb72
commit 2f1d473262
8 changed files with 51 additions and 23 deletions

View file

@ -20,5 +20,5 @@ public interface Suppressable extends Spell {
/**
* Event triggered when this effect is suppressed.
*/
void onSuppressed(Caster<?> otherSource);
void onSuppressed(Caster<?> otherSource, float suppressTime);
}

View file

@ -11,6 +11,7 @@ import com.minelittlepony.unicopia.ability.magic.Suppressable;
import com.minelittlepony.unicopia.ability.magic.spell.effect.AbstractSpell;
import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType;
import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits;
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
import com.minelittlepony.unicopia.entity.behaviour.EntityBehaviour;
import com.minelittlepony.unicopia.entity.behaviour.Disguise;
import com.minelittlepony.unicopia.entity.player.Pony;
@ -59,8 +60,9 @@ public class DisguiseSpell extends AbstractSpell implements Suppressable, Flight
}
@Override
public void onSuppressed(Caster<?> otherSource) {
suppressionCounter = 100;
public void onSuppressed(Caster<?> otherSource, float time) {
time /= getTraits().getOrDefault(Trait.STRENGTH, 1);
suppressionCounter = (int)(100 * time);
setDirty();
}

View file

@ -5,13 +5,13 @@ import com.minelittlepony.unicopia.ability.magic.Caster;
import com.minelittlepony.unicopia.ability.magic.spell.Situation;
import com.minelittlepony.unicopia.ability.magic.spell.ProjectileSpell;
import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits;
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
import com.minelittlepony.unicopia.block.state.StateMaps;
import com.minelittlepony.unicopia.particle.ParticleUtils;
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
import com.minelittlepony.unicopia.util.MagicalDamageSource;
import com.minelittlepony.unicopia.util.PosHelper;
import com.minelittlepony.unicopia.util.VecHelper;
import com.minelittlepony.unicopia.util.shape.Shape;
import com.minelittlepony.unicopia.util.shape.Sphere;
import net.minecraft.block.Block;
@ -36,9 +36,6 @@ import net.minecraft.world.explosion.Explosion.DestructionType;
* Simple fire spell that triggers an effect when used on a block.
*/
public class FireSpell extends AbstractSpell implements ProjectileSpell {
private static final Shape EFFECT_RANGE = new Sphere(false, 4);
protected FireSpell(SpellType<?> type, SpellTraits traits) {
super(type, traits);
}
@ -56,14 +53,14 @@ public class FireSpell extends AbstractSpell implements ProjectileSpell {
generateParticles(source);
}
return PosHelper.getAllInRegionMutable(source.getOrigin(), EFFECT_RANGE).reduce(false,
return PosHelper.getAllInRegionMutable(source.getOrigin(), new Sphere(false, Math.max(0, 4 + getTraits().get(Trait.POWER)))).reduce(false,
(r, i) -> applyBlocks(source.getWorld(), i),
(a, b) -> a || b)
|| applyEntities(null, source.getWorld(), source.getOriginVector());
}
protected void generateParticles(Caster<?> source) {
source.spawnParticles(EFFECT_RANGE, (1 + source.getLevel().get()) * 6, pos -> {
source.spawnParticles(new Sphere(false, Math.max(0, 4 + getTraits().get(Trait.POWER))), (1 + source.getLevel().get()) * 6, pos -> {
source.addParticle(ParticleTypes.LARGE_SMOKE, pos, Vec3d.ZERO);
});
}
@ -111,7 +108,7 @@ public class FireSpell extends AbstractSpell implements ProjectileSpell {
}
protected boolean applyEntities(Entity owner, World world, Vec3d pos) {
return !VecHelper.findInRange(owner, world, pos, 3, i -> applyEntitySingle(owner, world, i)).isEmpty();
return !VecHelper.findInRange(owner, world, pos, Math.max(0, 3 + getTraits().get(Trait.POWER)), i -> applyEntitySingle(owner, world, i)).isEmpty();
}
protected boolean applyEntitySingle(Entity owner, World world, Entity e) {

View file

@ -6,6 +6,7 @@ import java.util.List;
import com.minelittlepony.unicopia.ability.magic.Caster;
import com.minelittlepony.unicopia.ability.magic.spell.Situation;
import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits;
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
import com.minelittlepony.unicopia.entity.EntityReference;
import com.minelittlepony.unicopia.util.Weighted;
import com.minelittlepony.unicopia.util.shape.Shape;
@ -39,7 +40,11 @@ public class NecromancySpell extends AbstractSpell {
@Override
public boolean tick(Caster<?> source, Situation situation) {
int radius = (source.getLevel().get() + 1) * 4;
float radius = (source.getLevel().get() + 1) * 4 + getTraits().get(Trait.POWER);
if (radius <= 0) {
return false;
}
if (source.isClient()) {
source.spawnParticles(new Sphere(false, radius), 5, pos -> {
@ -56,7 +61,7 @@ public class NecromancySpell extends AbstractSpell {
summonedEntities.removeIf(ref -> !ref.isPresent(source.getWorld()));
float additional = source.getWorld().getLocalDifficulty(source.getOrigin()).getLocalDifficulty();
float additional = source.getWorld().getLocalDifficulty(source.getOrigin()).getLocalDifficulty() + getTraits().get(Trait.CHAOS, 0, 10);
Shape affectRegion = new Sphere(false, radius);

View file

@ -4,8 +4,8 @@ import com.minelittlepony.unicopia.ability.magic.Caster;
import com.minelittlepony.unicopia.ability.magic.SpellPredicate;
import com.minelittlepony.unicopia.ability.magic.spell.Situation;
import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits;
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
import com.minelittlepony.unicopia.particle.MagicParticleEffect;
import com.minelittlepony.unicopia.util.shape.Shape;
import com.minelittlepony.unicopia.util.shape.Sphere;
import net.minecraft.sound.SoundCategory;
@ -16,28 +16,33 @@ import net.minecraft.util.math.Vec3d;
* A spell for revealing changelings.
*/
public class RevealingSpell extends AbstractSpell {
private static final Shape AREA = new Sphere(false, 15);
protected RevealingSpell(SpellType<?> type, SpellTraits traits) {
super(type, traits);
}
@Override
public boolean tick(Caster<?> source, Situation situation) {
float range = Math.max(0, 15 + getTraits().get(Trait.POWER));
if (range == 0) {
return false;
}
if (source.isClient()) {
MagicParticleEffect effect = new MagicParticleEffect(getType().getColor());
source.spawnParticles(AREA, 5, pos -> {
source.spawnParticles(new Sphere(false, range), 5, pos -> {
source.addParticle(effect, pos, Vec3d.ZERO);
});
source.spawnParticles(effect, 5);
}
source.findAllSpellsInRange(15).forEach(e -> {
source.findAllSpellsInRange(range).forEach(e -> {
e.getSpellSlot().get(SpellPredicate.CAN_SUPPRESS, false)
.filter(spell -> spell.isVulnerable(source, this))
.ifPresent(spell -> {
spell.onSuppressed(source);
spell.onSuppressed(source, 1 + getTraits().get(Trait.STRENGTH));
source.getWorld().playSound(null, e.getOrigin(), SoundEvents.ENTITY_ZOMBIE_VILLAGER_CURE, SoundCategory.PLAYERS, 0.2F, 0.5F);
});
});

View file

@ -3,6 +3,7 @@ package com.minelittlepony.unicopia.ability.magic.spell.effect;
import com.minelittlepony.unicopia.ability.magic.Caster;
import com.minelittlepony.unicopia.ability.magic.spell.Situation;
import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits;
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
import com.minelittlepony.unicopia.block.state.StateMaps;
import com.minelittlepony.unicopia.particle.MagicParticleEffect;
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
@ -24,7 +25,7 @@ public class ScorchSpell extends FireSpell {
BlockPos pos = PosHelper.findSolidGroundAt(source.getWorld(), source.getOrigin(), source.getPhysics().getGravitySignum());
if (StateMaps.FIRE_AFFECTED.convert(source.getWorld(), pos)) {
source.spawnParticles(new Sphere(false, 1), 5, p -> {
source.spawnParticles(new Sphere(false, Math.max(1, getTraits().get(Trait.POWER))), 5, p -> {
source.addParticle(ParticleTypes.SMOKE, PosHelper.offset(p, pos), Vec3d.ZERO);
});
}

View file

@ -12,6 +12,7 @@ import com.minelittlepony.unicopia.ability.magic.Caster;
import com.minelittlepony.unicopia.ability.magic.spell.Situation;
import com.minelittlepony.unicopia.ability.magic.spell.ProjectileSpell;
import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits;
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.item.FriendshipBraceletItem;
import com.minelittlepony.unicopia.item.enchantment.UEnchantments;
@ -78,12 +79,18 @@ public class ShieldSpell extends AbstractSpell implements ProjectileSpell {
return true;
}
float knowledge = getTraits().get(Trait.KNOWLEDGE, -6, 6);
if (knowledge == 0) {
knowledge = 1;
}
long costMultiplier = applyEntities(source);
if (costMultiplier > 0) {
double cost = 2 + source.getLevel().get();
cost *= costMultiplier / ((1 + source.getLevel().get()) * 3F);
cost /= 2.725D;
cost /= knowledge;
if (!source.subtractEnergyCost(cost)) {
setDead();
@ -98,7 +105,8 @@ public class ShieldSpell extends AbstractSpell implements ProjectileSpell {
*/
public double getDrawDropOffRange(Caster<?> source) {
float multiplier = source.getMaster().isSneaking() ? 1 : 2;
return (4 + (source.getLevel().get() * 2)) / multiplier;
float min = 4 + getTraits().get(Trait.POWER);
return (min + (source.getLevel().get() * 2)) / multiplier;
}
protected List<Entity> getTargets(Caster<?> source, double radius) {

View file

@ -27,6 +27,7 @@ import net.minecraft.nbt.NbtElement;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.text.LiteralText;
import net.minecraft.text.Text;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.registry.Registry;
public final class SpellTraits implements Iterable<Map.Entry<Trait, Float>> {
@ -62,7 +63,7 @@ public final class SpellTraits implements Iterable<Map.Entry<Trait, Float>> {
public boolean includes(SpellTraits other) {
return other.stream().allMatch(pair -> {
return getAmount(pair.getKey()) >= pair.getValue();
return get(pair.getKey()) >= pair.getValue();
});
}
@ -79,8 +80,17 @@ public final class SpellTraits implements Iterable<Map.Entry<Trait, Float>> {
return entries().stream();
}
public float getAmount(Trait trait) {
return traits.getOrDefault(trait, 0F);
public float getOrDefault(Trait trait, float def) {
float i = traits.getOrDefault(trait, def);
return i == 0 ? def : i;
}
public float get(Trait trait) {
return getOrDefault(trait, 0F);
}
public float get(Trait trait, float min, float max) {
return MathHelper.clamp(get(trait), min, max);
}
public void appendTooltip(List<Text> tooltip) {