mirror of
https://github.com/Sollace/Unicopia.git
synced 2025-02-08 06:26:43 +01:00
Spells now have their own affinity and can only be used with gems of a matching type
This commit is contained in:
parent
79e9b310d3
commit
0af6a52719
18 changed files with 173 additions and 61 deletions
|
@ -1,10 +1,11 @@
|
|||
package com.minelittlepony.unicopia.item;
|
||||
|
||||
import com.minelittlepony.unicopia.spell.IAligned;
|
||||
import com.minelittlepony.unicopia.spell.SpellAffinity;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
public interface IMagicalItem {
|
||||
public interface IMagicalItem extends IAligned {
|
||||
/**
|
||||
* If true this item serves as host to its own inner dimensional space.
|
||||
* Bag of Holding will explode if you try to store items of this kind inside of it.
|
||||
|
@ -18,6 +19,6 @@ public interface IMagicalItem {
|
|||
* What this returns may have effects on the behaviour of certain spells and effects.
|
||||
*/
|
||||
default SpellAffinity getAffinity(ItemStack stack) {
|
||||
return SpellAffinity.NEUTRAL;
|
||||
return getAffinity();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ public class ItemCurse extends ItemSpell {
|
|||
}
|
||||
|
||||
@Override
|
||||
public SpellAffinity getAffinity(ItemStack stack) {
|
||||
public SpellAffinity getAffinity() {
|
||||
return SpellAffinity.BAD;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import com.minelittlepony.unicopia.Predicates;
|
|||
import com.minelittlepony.unicopia.UClient;
|
||||
import com.minelittlepony.unicopia.inventory.ContainerOfHolding;
|
||||
import com.minelittlepony.unicopia.inventory.InventoryOfHolding;
|
||||
import com.minelittlepony.unicopia.spell.SpellAffinity;
|
||||
import com.minelittlepony.util.vector.VecHelper;
|
||||
|
||||
import net.minecraft.client.util.ITooltipFlag;
|
||||
|
@ -121,6 +122,11 @@ public class ItemOfHolding extends Item implements IMagicalItem {
|
|||
return new ActionResult<>(EnumActionResult.SUCCESS, stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpellAffinity getAffinity() {
|
||||
return SpellAffinity.NEUTRAL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasInnerSpace() {
|
||||
return true;
|
||||
|
|
|
@ -184,7 +184,7 @@ public class ItemSpell extends Item implements ICastable {
|
|||
if (SpellRegistry.stackHasEnchantment(stack)) {
|
||||
SpellAffinity affinity = getAffinity(stack);
|
||||
|
||||
tooltip.add(affinity.getColourCode() + I18n.format(String.format("%s.%s.name",
|
||||
tooltip.add(affinity.getColourCode() + I18n.format(String.format("%s.%s.tagline",
|
||||
affinity.getTranslationKey(),
|
||||
SpellRegistry.getKeyFromStack(stack)
|
||||
)));
|
||||
|
@ -213,7 +213,7 @@ public class ItemSpell extends Item implements ICastable {
|
|||
super.getSubItems(tab, subItems);
|
||||
|
||||
if (isInCreativeTab(tab)) {
|
||||
for (String name : SpellRegistry.instance().getAllNames()) {
|
||||
for (String name : SpellRegistry.instance().getAllNames(getAffinity())) {
|
||||
subItems.add(SpellRegistry.instance().enchantStack(new ItemStack(this, 1), name));
|
||||
}
|
||||
}
|
||||
|
@ -236,7 +236,7 @@ public class ItemSpell extends Item implements ICastable {
|
|||
}
|
||||
|
||||
@Override
|
||||
public SpellAffinity getAffinity(ItemStack stack) {
|
||||
public SpellAffinity getAffinity() {
|
||||
return SpellAffinity.GOOD;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,11 @@ public abstract class AbstractSpell implements IMagicEffect {
|
|||
@Override
|
||||
public void setCurrentLevel(int level) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCraftable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
package com.minelittlepony.unicopia.spell;
|
||||
|
||||
/**
|
||||
* Interface for things that have an affine alignment.
|
||||
*/
|
||||
public interface IAligned {
|
||||
/**
|
||||
* Gets the current alignment.
|
||||
* Good/Bad/Neutral
|
||||
*/
|
||||
SpellAffinity getAffinity();
|
||||
}
|
|
@ -15,14 +15,12 @@ import net.minecraft.util.math.BlockPos;
|
|||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public interface ICaster<E extends EntityLivingBase> extends IOwned<E>, ILevelled {
|
||||
public interface ICaster<E extends EntityLivingBase> extends IOwned<E>, ILevelled, IAligned {
|
||||
|
||||
void setEffect(IMagicEffect effect);
|
||||
|
||||
IMagicEffect getEffect();
|
||||
|
||||
SpellAffinity getAffinity();
|
||||
|
||||
default boolean hasEffect() {
|
||||
return getEffect() != null;
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import com.minelittlepony.unicopia.util.serialisation.InbtSerialisable;
|
|||
/**
|
||||
* Interface for a magic spells
|
||||
*/
|
||||
public interface IMagicEffect extends InbtSerialisable, ILevelled {
|
||||
public interface IMagicEffect extends InbtSerialisable, ILevelled, IAligned {
|
||||
|
||||
/**
|
||||
* Gets the name used to identify this effect.
|
||||
|
@ -27,6 +27,11 @@ public interface IMagicEffect extends InbtSerialisable, ILevelled {
|
|||
*/
|
||||
boolean getDead();
|
||||
|
||||
/**
|
||||
* Returns true if this effect can be crafted into a gem.
|
||||
*/
|
||||
boolean isCraftable();
|
||||
|
||||
/**
|
||||
* Called when first attached to a gem.
|
||||
*/
|
||||
|
|
|
@ -11,6 +11,8 @@ public enum SpellAffinity {
|
|||
|
||||
private final int corruption;
|
||||
|
||||
private SpellAffinity[] implications;
|
||||
|
||||
SpellAffinity(TextFormatting color, int corruption) {
|
||||
this.color = color;
|
||||
this.corruption = corruption;
|
||||
|
@ -31,4 +33,18 @@ public enum SpellAffinity {
|
|||
public boolean isNeutral() {
|
||||
return this == NEUTRAL;
|
||||
}
|
||||
|
||||
public SpellAffinity[] getImplicators() {
|
||||
if (implications != null) {
|
||||
return implications;
|
||||
}
|
||||
|
||||
if (this == NEUTRAL) {
|
||||
implications = values();
|
||||
} else {
|
||||
implications = new SpellAffinity[] { this };
|
||||
}
|
||||
|
||||
return implications;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,6 +32,11 @@ public class SpellCharge extends AbstractSpell {
|
|||
return "charge";
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpellAffinity getAffinity() {
|
||||
return SpellAffinity.GOOD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTint() {
|
||||
return 0x0000AA;
|
||||
|
|
|
@ -31,6 +31,16 @@ public class SpellDisguise extends AbstractSpell {
|
|||
return "disguise";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCraftable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpellAffinity getAffinity() {
|
||||
return SpellAffinity.BAD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTint() {
|
||||
return 0;
|
||||
|
|
|
@ -73,6 +73,11 @@ public class SpellFire extends AbstractSpell implements IUseAction, IDispenceabl
|
|||
return "fire";
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpellAffinity getAffinity() {
|
||||
return SpellAffinity.GOOD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTint() {
|
||||
return 0xFF0000;
|
||||
|
|
|
@ -61,6 +61,11 @@ public class SpellIce extends AbstractSpell implements IUseAction, IDispenceable
|
|||
return "ice";
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpellAffinity getAffinity() {
|
||||
return SpellAffinity.GOOD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTint() {
|
||||
return 0xADD8E6;
|
||||
|
|
|
@ -67,6 +67,11 @@ public class SpellPortal extends AbstractSpell implements IUseAction {
|
|||
return 0x384C38;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpellAffinity getAffinity() {
|
||||
return SpellAffinity.GOOD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDead() {
|
||||
super.setDead();
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
package com.minelittlepony.unicopia.spell;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
|
@ -23,7 +26,9 @@ public class SpellRegistry {
|
|||
return stack.hasTagCompound() && stack.getTagCompound().hasKey("spell");
|
||||
}
|
||||
|
||||
private final Map<String, Entry> entries = new HashMap<>();
|
||||
private final Map<String, Entry<?>> entries = new HashMap<>();
|
||||
|
||||
private final Map<SpellAffinity, Set<String>> keysByAffinity = new HashMap<>();
|
||||
|
||||
private SpellRegistry() {
|
||||
registerSpell(SpellShield::new);
|
||||
|
@ -35,6 +40,7 @@ public class SpellRegistry {
|
|||
registerSpell(SpellDisguise::new);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public IMagicEffect getSpellFromName(String name) {
|
||||
if (entries.containsKey(name)) {
|
||||
return entries.get(name).create();
|
||||
|
@ -65,41 +71,28 @@ public class SpellRegistry {
|
|||
return compound;
|
||||
}
|
||||
|
||||
private Optional<Entry<?>> getEntryFromStack(ItemStack stack) {
|
||||
return Optional.ofNullable(entries.get(getKeyFromStack(stack)));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public IDispenceable getDispenseActionFrom(ItemStack stack) {
|
||||
String key = getKeyFromStack(stack);
|
||||
|
||||
if (entries.containsKey(key)) {
|
||||
Entry entry = entries.get(key);
|
||||
if (entry.canDispense) {
|
||||
return entry.create();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return getEntryFromStack(stack).map(Entry::dispensable).orElse(null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public IUseAction getUseActionFrom(ItemStack stack) {
|
||||
String key = getKeyFromStack(stack);
|
||||
|
||||
if (entries.containsKey(key)) {
|
||||
Entry entry = entries.get(key);
|
||||
if (entry.canUse) {
|
||||
return entry.create();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return getEntryFromStack(stack).map(Entry::useable).orElse(null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public IMagicEffect getSpellFromItemStack(ItemStack stack) {
|
||||
return getSpellFromName(getKeyFromStack(stack));
|
||||
}
|
||||
|
||||
public void registerSpell(Callable<IMagicEffect> factory) {
|
||||
public <T extends IMagicEffect> void registerSpell(Callable<T> factory) {
|
||||
try {
|
||||
new Entry(factory);
|
||||
new Entry<T>(factory);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
@ -118,10 +111,7 @@ public class SpellRegistry {
|
|||
}
|
||||
|
||||
public ItemStack enchantStack(ItemStack stack, ItemStack from) {
|
||||
stack.setTagCompound(new NBTTagCompound());
|
||||
stack.getTagCompound().setString("spell", getKeyFromStack(from));
|
||||
|
||||
return stack;
|
||||
return enchantStack(stack, getKeyFromStack(from));
|
||||
}
|
||||
|
||||
public ItemStack enchantStack(ItemStack stack, String name) {
|
||||
|
@ -152,33 +142,58 @@ public class SpellRegistry {
|
|||
return 0xffffff;
|
||||
}
|
||||
|
||||
public Set<String> getAllNames() {
|
||||
return entries.keySet();
|
||||
public Set<String> getAllNames(SpellAffinity affinity) {
|
||||
return keysByAffinity.get(affinity);
|
||||
}
|
||||
|
||||
class Entry {
|
||||
Callable<IMagicEffect> factory;
|
||||
@Immutable
|
||||
class Entry<T extends IMagicEffect> {
|
||||
final Callable<T> factory;
|
||||
|
||||
int color;
|
||||
final int color;
|
||||
|
||||
boolean canDispense;
|
||||
boolean canUse;
|
||||
final boolean canDispense;
|
||||
final boolean canUse;
|
||||
|
||||
Entry(Callable<IMagicEffect> factory) throws Exception {
|
||||
IMagicEffect inst = factory.call();
|
||||
final SpellAffinity affinity;
|
||||
|
||||
Entry(Callable<T> factory) throws Exception {
|
||||
T inst = factory.call();
|
||||
|
||||
this.factory = factory;
|
||||
this.color = inst.getTint();
|
||||
this.canDispense = inst instanceof IDispenceable;
|
||||
this.canUse = inst instanceof IUseAction;
|
||||
this.affinity = inst.getAffinity();
|
||||
|
||||
if (inst.isCraftable()) {
|
||||
for (SpellAffinity affinity : affinity.getImplicators()) {
|
||||
keysByAffinity.computeIfAbsent(affinity, a -> new HashSet<>()).add(inst.getName());
|
||||
}
|
||||
}
|
||||
|
||||
entries.put(inst.getName(), this);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
<T extends IMagicEffect> T create() {
|
||||
IUseAction useable() {
|
||||
if (!canUse) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (IUseAction)create();
|
||||
}
|
||||
|
||||
IDispenceable dispensable() {
|
||||
if (!canDispense) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (IDispenceable)create();
|
||||
}
|
||||
|
||||
T create() {
|
||||
try {
|
||||
return (T) factory.call();
|
||||
return factory.call();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
|
|
@ -35,6 +35,11 @@ public class SpellShield extends AbstractSpell {
|
|||
return "shield";
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpellAffinity getAffinity() {
|
||||
return SpellAffinity.NEUTRAL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTint() {
|
||||
return 0x66CDAA;
|
||||
|
|
|
@ -3,6 +3,7 @@ package com.minelittlepony.unicopia.spell;
|
|||
import com.minelittlepony.unicopia.UParticles;
|
||||
import com.minelittlepony.unicopia.particle.Particles;
|
||||
import com.minelittlepony.unicopia.player.PlayerSpeciesList;
|
||||
import com.minelittlepony.util.MagicalDamageSource;
|
||||
import com.minelittlepony.util.shape.Sphere;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
|
@ -16,6 +17,11 @@ public class SpellVortex extends SpellShield {
|
|||
return "vortex";
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpellAffinity getAffinity() {
|
||||
return SpellAffinity.NEUTRAL;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void spawnParticles(ICaster<?> source, int strength) {
|
||||
Vec3d pos = source.getOriginVector();
|
||||
|
@ -35,6 +41,10 @@ public class SpellVortex extends SpellShield {
|
|||
force *= calculateAdjustedForce(PlayerSpeciesList.instance().getPlayer((EntityPlayer)target));
|
||||
}
|
||||
|
||||
if (source.getAffinity() == SpellAffinity.BAD && source.getWorld().rand.nextInt(4500) == 0) {
|
||||
source.getEntity().attackEntityFrom(MagicalDamageSource.create("vortex"), 4);
|
||||
}
|
||||
|
||||
applyForce(pos, target, -force, 0);
|
||||
|
||||
float maxVel = source.getAffinity() == SpellAffinity.BAD ? 1 : 1.6f;
|
||||
|
|
|
@ -31,22 +31,31 @@ item.corrupted_gem.name=Fractured Gem
|
|||
item.corrupted_gem.enchanted.name=Fractured Gem of %s
|
||||
|
||||
spell.shield.name=Defense
|
||||
spell.charge.name=Chanelling
|
||||
spell.fire.name=Flame
|
||||
spell.infero.name=Burning
|
||||
spell.ice.name=Frost
|
||||
spell.shield.tagline=Protection I
|
||||
|
||||
spell.portal.name=Transportation
|
||||
spell.portal.tagline=Teleportation I
|
||||
|
||||
spell.fire.name=Flame
|
||||
spell.fire.tagline=Fire I
|
||||
|
||||
spell.vortex.name=Retention
|
||||
spell.minion.name=Obedience
|
||||
spell.vortex.tagline=Containment I
|
||||
|
||||
spell.charge.name=Chanelling
|
||||
spell.charge.tagline=Energy I
|
||||
|
||||
spell.ice.name=Frost
|
||||
spell.ice.tagline=Ice I
|
||||
|
||||
curse.shield.name=Repulsion
|
||||
curse.charge.name=Draining
|
||||
curse.fire.name=Hades
|
||||
curse.inferno.name=Inferno
|
||||
curse.ice.name=Freezing
|
||||
curse.portal.name=Summoning
|
||||
curse.attract.name=Entrapment
|
||||
curse.minion.name=Slavery
|
||||
curse.shield.tagline=Hostility I
|
||||
|
||||
curse.vortex.name=Suffering
|
||||
curse.vortex.tagline=Torture I
|
||||
|
||||
curse.necromany.name=Necromancy
|
||||
curse.necromancy.tagline=Resurrection I
|
||||
|
||||
item.spellbook.name=Spellbook
|
||||
item.bag_of_holding.name=Bag of Holding
|
||||
|
|
Loading…
Reference in a new issue