Beginning of soul system

This commit is contained in:
Nicholas Ignoffo 2018-09-29 16:49:05 -07:00
parent 85733d44d3
commit 23ae02af78
45 changed files with 713 additions and 10 deletions

View file

@ -3,7 +3,8 @@ package com.wayoftime.bloodmagic.core;
import com.google.common.collect.Lists;
import com.wayoftime.bloodmagic.BloodMagic;
import com.wayoftime.bloodmagic.core.network.BloodOrb;
import com.wayoftime.bloodmagic.core.type.DemonWillType;
import com.wayoftime.bloodmagic.core.util.register.IModelLocator;
import com.wayoftime.bloodmagic.core.will.DemonWill;
import com.wayoftime.bloodmagic.core.type.SlateType;
import com.wayoftime.bloodmagic.core.util.register.IItemProvider;
import com.wayoftime.bloodmagic.core.util.register.IVariantProvider;
@ -62,6 +63,8 @@ public class RegistrarBloodMagicItems {
public static final Item LIVING_ARMOR_FEET = Items.AIR;
public static final Item LIVING_TOME = Items.AIR;
public static final Item SENTIENT_SWORD = Items.AIR;
public static final Item MONSTER_SOUL = Items.AIR;
public static final Item DEMON_WILL_CRYSTAL_RAW = Items.AIR;
public static final Item DEMON_WILL_CRYSTAL_CORROSIVE = Items.AIR;
public static final Item DEMON_WILL_CRYSTAL_DESTRUCTIVE = Items.AIR;
@ -100,13 +103,16 @@ public class RegistrarBloodMagicItems {
new ItemLivingArmor(EntityEquipmentSlot.CHEST),
new ItemLivingArmor(EntityEquipmentSlot.LEGS),
new ItemLivingArmor(EntityEquipmentSlot.FEET),
new ItemLivingTome(),
new ItemAltarBuilder()
new ItemAltarBuilder(),
new ItemSentientSword(),
new ItemMonsterSoul()
));
for (DemonWillType type : DemonWillType.VALUES)
for (DemonWill type : DemonWill.VALUES)
items.add(new ItemMundane("demon_will_crystal_" + type.getName()));
items.add(new ItemLivingTome()); // Last so it's at the bottom of the creative tab
registry.registerAll(items.toArray(new Item[0]));
}
@ -116,17 +122,27 @@ public class RegistrarBloodMagicItems {
for (Item item : items) {
boolean flag = handleModel(item);
if (!flag) // If we haven't registered a model by now, we don't need any special handling so we'll just use the default model.
ModelLoader.setCustomModelResourceLocation(item, 0, new ModelResourceLocation(item.getRegistryName(), item instanceof ItemBlock ? "normal" : "inventory"));
if (!flag) { // If we haven't registered a model by now, we don't need any special handling so we'll just use the default model.
ResourceLocation modelPath = item.getRegistryName();
if (item instanceof IModelLocator)
modelPath = ((IModelLocator) item).getModelPath();
ModelLoader.setCustomModelResourceLocation(item, 0, new ModelResourceLocation(modelPath, item instanceof ItemBlock ? "normal" : "inventory"));
}
}
}
static boolean handleModel(Item item) {
if (item instanceof IVariantProvider) {
ResourceLocation modelPath = item.getRegistryName();
if (item instanceof IModelLocator)
modelPath = ((IModelLocator) item).getModelPath();
Int2ObjectMap<String> variants = new Int2ObjectOpenHashMap<>();
((IVariantProvider) item).collectVariants(variants);
for (Int2ObjectMap.Entry<String> entry : variants.int2ObjectEntrySet())
ModelLoader.setCustomModelResourceLocation(item, entry.getIntKey(), new ModelResourceLocation(item.getRegistryName(), entry.getValue()));
ModelLoader.setCustomModelResourceLocation(item, entry.getIntKey(), new ModelResourceLocation(modelPath, entry.getValue()));
return true;
}

View file

@ -0,0 +1,31 @@
package com.wayoftime.bloodmagic.core.util;
import com.google.common.collect.Lists;
import net.minecraft.item.ItemStack;
import net.minecraftforge.items.IItemHandler;
import javax.annotation.Nonnull;
import java.util.Collections;
import java.util.List;
import java.util.function.Predicate;
public class InventoryUtil {
public static final Predicate<ItemStack> NO_EMPTY = stack -> !stack.isEmpty();
@Nonnull
public static List<ItemStack> findMatchingItems(IItemHandler inventory, Predicate<ItemStack> filter) {
List<ItemStack> found = null;
for (int i = 0; i < inventory.getSlots(); i++) {
ItemStack stack = inventory.getStackInSlot(i);
if (filter.test(stack)) {
if (found == null)
found = Lists.newArrayList();
found.add(stack);
}
}
return found == null ? Collections.emptyList() : found;
}
}

View file

@ -0,0 +1,40 @@
package com.wayoftime.bloodmagic.core.util;
import java.util.Objects;
public class ModifiableValue<T> {
private T value;
public ModifiableValue(T value) {
this.value = value;
}
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ModifiableValue)) return false;
ModifiableValue<?> that = (ModifiableValue<?>) o;
return value != null ? value.equals(that.value) : that.value == null;
}
@Override
public int hashCode() {
return value != null ? value.hashCode() : 0;
}
@Override
public String toString() {
return Objects.toString(value);
}
}

View file

@ -0,0 +1,16 @@
package com.wayoftime.bloodmagic.core.util.register;
import net.minecraft.util.ResourceLocation;
import javax.annotation.Nonnull;
public interface IModelLocator {
/**
* Allows an item to point to a custom model path instead of using the registry name.
*
* @return the path to the model.
*/
@Nonnull
ResourceLocation getModelPath();
}

View file

@ -1,10 +1,10 @@
package com.wayoftime.bloodmagic.core.type;
package com.wayoftime.bloodmagic.core.will;
import net.minecraft.util.IStringSerializable;
import java.util.Locale;
public enum DemonWillType implements IStringSerializable {
public enum DemonWill implements IStringSerializable {
RAW,
CORROSIVE,
@ -13,7 +13,7 @@ public enum DemonWillType implements IStringSerializable {
STEADFAST,
;
public static final DemonWillType[] VALUES = values();
public static final DemonWill[] VALUES = values();
@Override
public String getName() {

View file

@ -0,0 +1,67 @@
package com.wayoftime.bloodmagic.core.will;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraftforge.common.util.INBTSerializable;
import javax.annotation.Nullable;
public class DemonWillHolder implements INBTSerializable<NBTTagCompound> {
private DemonWill type;
private double amount;
public DemonWillHolder(DemonWill type, double amount) {
this.type = type;
this.amount = amount;
}
private DemonWillHolder() {
// No-op
}
public DemonWill getType() {
return type;
}
public double getAmount() {
return amount;
}
public void setAmount(double amount) {
this.amount = amount;
}
public void modifyAmount(double change) {
this.amount += change;
}
@Override
public NBTTagCompound serializeNBT() {
NBTTagCompound tag = new NBTTagCompound();
tag.setInteger("type", type.ordinal());
tag.setDouble("amount", amount);
return tag;
}
@Override
public void deserializeNBT(NBTTagCompound nbt) {
this.type = DemonWill.VALUES[nbt.getInteger("type")];
this.amount = nbt.getDouble("amount");
}
@Nullable
public static DemonWillHolder fromStack(ItemStack stack) {
if (!stack.hasTagCompound()) // Definitely hasn't been bound yet.
return null;
NBTBase willTag = stack.getTagCompound().getTag("demonWill");
if (willTag.getId() != 10 || willTag.isEmpty()) // Make sure it's both a tag compound and that it has actual data.
return null;
DemonWillHolder holder = new DemonWillHolder();
holder.deserializeNBT((NBTTagCompound) willTag);
return holder;
}
}

View file

@ -0,0 +1,100 @@
package com.wayoftime.bloodmagic.core.will;
import com.wayoftime.bloodmagic.BloodMagic;
import com.wayoftime.bloodmagic.core.RegistrarBloodMagicItems;
import com.wayoftime.bloodmagic.core.util.InventoryUtil;
import com.wayoftime.bloodmagic.event.DemonicWillEvent;
import net.minecraft.entity.Entity;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.monster.IMob;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumHand;
import net.minecraft.world.EnumDifficulty;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.util.FakePlayer;
import net.minecraftforge.event.entity.living.LivingDropsEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import java.util.function.Predicate;
@Mod.EventBusSubscriber(modid = BloodMagic.MODID)
public class DemonicWillEventHandler {
@SubscribeEvent
public static void gatherDrops(LivingDropsEvent event) {
if (!(event.getEntityLiving() instanceof IMob) && event.getEntityLiving().getEntityWorld().getDifficulty() != EnumDifficulty.PEACEFUL)
return;
Entity sourceEntity = event.getSource().getTrueSource();
if (!(sourceEntity instanceof EntityPlayer) || sourceEntity instanceof FakePlayer)
return;
EntityPlayer player = (EntityPlayer) sourceEntity;
ItemStack held = player.getHeldItem(EnumHand.MAIN_HAND);
if (held.isEmpty() || !(held.getItem() instanceof ISentientEquipment))
return;
DemonWillHolder willDrop = ((ISentientEquipment) held.getItem()).getWillDrop(player, event.getEntityLiving(), held, event.getLootingLevel());
if (willDrop == null)
return;
DemonicWillEvent.GatherWillDrops willDropEvent = new DemonicWillEvent.GatherWillDrops(player, event.getEntityLiving(), held, event.getLootingLevel(), willDrop.getAmount());
if (MinecraftForge.EVENT_BUS.post(willDropEvent))
return;
willDrop.setAmount(willDropEvent.getDroppedWill());
IItemHandler inventory = player.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null);
if (inventory == null)
return; // shut up intellij this is never going to happen
InventoryUtil.findMatchingItems(inventory, InventoryUtil.NO_EMPTY.and(new WillContainerFilter(willDrop.getType()))).forEach(stack -> {
if (willDrop.getAmount() <= 0)
return;
IWillContainer container = (IWillContainer) stack.getItem();
DemonWillHolder holder = container.getDemonWill(stack);
if (holder == null)
holder = new DemonWillHolder(willDrop.getType(), 0);
holder.modifyAmount(Math.min(willDrop.getAmount(), container.getMaxContained(stack)));
willDrop.modifyAmount(-holder.getAmount());
});
if (willDrop.getAmount() >= 0) {
ItemStack drop = new ItemStack(RegistrarBloodMagicItems.MONSTER_SOUL);
((IWillContainer) drop.getItem()).applyDemonWill(drop, willDrop);
event.getDrops().add(new EntityItem(player.getEntityWorld(), event.getEntity().posX, event.getEntity().posY, event.getEntity().posZ, drop));
}
}
private static class WillContainerFilter implements Predicate<ItemStack> {
private final DemonWill type;
public WillContainerFilter(DemonWill type) {
this.type = type;
}
@Override
public boolean test(ItemStack stack) {
if (stack.getItem() instanceof IWillContainer) {
IWillContainer container = (IWillContainer) stack.getItem();
double max = container.getMaxContained(stack);
DemonWillHolder holder = container.getDemonWill(stack);
if (holder == null)
return true;
if (holder.getType() != type)
return false;
return holder.getAmount() < max;
}
return false;
}
}
}

View file

@ -0,0 +1,43 @@
package com.wayoftime.bloodmagic.core.will;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.monster.EntitySlime;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import javax.annotation.Nullable;
public interface ISentientEquipment {
@Nullable
default DemonWillHolder getWillDrop(EntityPlayer player, EntityLivingBase attacked, ItemStack stack, int looting) {
double willModifier = attacked instanceof EntitySlime ? 0.67 : 1;
DemonWill type = getDemonWill(stack);
DemonWillHolder ret = null;
for (int i = 0; i <= looting; i++) {
if (i == 0 || player.getEntityWorld().rand.nextDouble() <= 0.4) {
if (ret == null)
ret = new DemonWillHolder(type, 0);
ret.modifyAmount(willModifier * (getWillDropAmount(stack) * player.getEntityWorld().rand.nextDouble() * (attacked.getMaxHealth() / 20D)));
}
}
return ret;
}
double getWillDropAmount(ItemStack stack);
default boolean isActivated(ItemStack stack) {
return stack.hasTagCompound() && stack.getTagCompound().getBoolean("sentientActivated");
}
default DemonWill getDemonWill(ItemStack stack) {
NBTTagCompound tagCompound = stack.getTagCompound();
if (tagCompound == null || !tagCompound.hasKey("willType"))
return DemonWill.RAW;
return DemonWill.valueOf(tagCompound.getString("willType"));
}
}

View file

@ -0,0 +1,38 @@
package com.wayoftime.bloodmagic.core.will;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import javax.annotation.Nullable;
import java.util.List;
public interface IWillContainer {
double getMaxContained(ItemStack stack);
@Nullable
default DemonWillHolder getDemonWill(ItemStack stack) {
return DemonWillHolder.fromStack(stack);
}
default void applyDemonWill(ItemStack stack, DemonWillHolder holder) {
NBTTagCompound tag = stack.getTagCompound();
if (tag == null)
stack.setTagCompound(tag = new NBTTagCompound());
tag.setTag("demonWill", holder.serializeNBT());
}
static void appendTooltip(ItemStack stack, List<String> tooltip) {
if (!(stack.getItem() instanceof IWillContainer))
return;
DemonWillHolder holder = ((IWillContainer) stack.getItem()).getDemonWill(stack);
if (holder == null)
return;
// TODO - Localize
tooltip.add("Will: " + holder.getType());
tooltip.add("Amount: " + holder.getAmount());
}
}

View file

@ -0,0 +1,52 @@
package com.wayoftime.bloodmagic.event;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fml.common.eventhandler.Cancelable;
import net.minecraftforge.fml.common.eventhandler.Event;
public class DemonicWillEvent extends Event {
@Cancelable
public static class GatherWillDrops extends DemonicWillEvent {
private final EntityPlayer player;
private final EntityLivingBase attacked;
private final ItemStack stack;
private final int looting;
private double droppedWill;
public GatherWillDrops(EntityPlayer player, EntityLivingBase attacked, ItemStack stack, int looting, double droppedWill) {
this.player = player;
this.attacked = attacked;
this.stack = stack;
this.looting = looting;
this.droppedWill = droppedWill;
}
public EntityPlayer getPlayer() {
return player;
}
public EntityLivingBase getAttacked() {
return attacked;
}
public ItemStack getStack() {
return stack;
}
public int getLooting() {
return looting;
}
public double getDroppedWill() {
return droppedWill;
}
public void setDroppedWill(double droppedWill) {
this.droppedWill = droppedWill;
}
}
}

View file

@ -0,0 +1,56 @@
package com.wayoftime.bloodmagic.item;
import com.wayoftime.bloodmagic.BloodMagic;
import com.wayoftime.bloodmagic.core.util.register.IModelLocator;
import com.wayoftime.bloodmagic.core.will.DemonWill;
import com.wayoftime.bloodmagic.core.will.DemonWillHolder;
import com.wayoftime.bloodmagic.core.will.IWillContainer;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.ItemStack;
import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
public class ItemMonsterSoul extends ItemMundane implements IWillContainer, IModelLocator {
public ItemMonsterSoul() {
super("monster_soul");
setMaxStackSize(1);
addPropertyOverride(new ResourceLocation(BloodMagic.MODID, "will"), (stack, worldIn, entityIn) -> {
DemonWillHolder holder = getDemonWill(stack);
return holder == null || holder.getType() == DemonWill.RAW ? 0F : Float.parseFloat("0." + holder.getType().ordinal());
});
}
@Override
public void getSubItems(CreativeTabs tab, NonNullList<ItemStack> items) {
for (DemonWill will : DemonWill.VALUES) {
ItemStack stack = new ItemStack(this);
applyDemonWill(stack, new DemonWillHolder(will, 0));
items.add(stack);
}
}
@Override
public void addInformation(ItemStack stack, @Nullable World worldIn, List<String> tooltip, ITooltipFlag flagIn) {
IWillContainer.appendTooltip(stack, tooltip);
}
@Override
public double getMaxContained(ItemStack stack) {
DemonWillHolder holder = getDemonWill(stack);
return holder == null ? Double.MAX_VALUE : holder.getAmount();
}
@Nonnull
@Override
public ResourceLocation getModelPath() {
return new ResourceLocation(BloodMagic.MODID, "soul/monster_soul");
}
}

View file

@ -0,0 +1,50 @@
package com.wayoftime.bloodmagic.item;
import com.wayoftime.bloodmagic.BloodMagic;
import com.wayoftime.bloodmagic.core.util.register.IModelLocator;
import com.wayoftime.bloodmagic.core.will.DemonWill;
import com.wayoftime.bloodmagic.core.will.ISentientEquipment;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemSword;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation;
import javax.annotation.Nonnull;
public class ItemSentientSword extends ItemSword implements ISentientEquipment, IModelLocator {
public ItemSentientSword() {
super(ToolMaterial.IRON);
setRegistryName("sentient_sword");
setTranslationKey(BloodMagic.MODID + ":sentient_sword");
setCreativeTab(BloodMagic.TAB_BM);
addPropertyOverride(new ResourceLocation(BloodMagic.MODID, "will"), (stack, worldIn, entityIn) -> Float.parseFloat("0." + getDemonWill(stack).ordinal()));
addPropertyOverride(new ResourceLocation(BloodMagic.MODID, "active"), (stack, worldIn, entityIn) -> isActivated(stack) ? 1.0F : 0.0F);
}
@Override
public void getSubItems(CreativeTabs tab, NonNullList<ItemStack> items) {
for (DemonWill will : DemonWill.VALUES) {
ItemStack stack = new ItemStack(this);
NBTTagCompound tag = new NBTTagCompound();
tag.setString("willType", will.name());
stack.setTagCompound(tag);
items.add(stack);
}
}
@Override
public double getWillDropAmount(ItemStack stack) {
return 1;
}
@Nonnull
@Override
public ResourceLocation getModelPath() {
return new ResourceLocation(BloodMagic.MODID, "soul/sentient_sword");
}
}

View file

@ -57,6 +57,8 @@ item.bloodmagic:demon_will_crystal_corrosive.name=Corrosive Demon Will Crystal
item.bloodmagic:demon_will_crystal_destructive.name=Destructive Demon Will Crystal
item.bloodmagic:demon_will_crystal_vengeful.name=Vengeful Demon Will Crystal
item.bloodmagic:demon_will_crystal_steadfast.name=Steadfast Demon Will Crystal
item.bloodmagic:sentient_sword.name=Sentient Sword
item.bloodmagic:monster_soul.name=Monster Soul
# Death
@ -68,6 +70,9 @@ fluid.bloodmagic:life_essence=Life Essence
# Living Upgrades
upgrade.bloodmagic:arrow_protect.name=Arrow Protect
upgrade.bloodmagic:arrow_shot.name=Arrow Shot
upgrade.bloodmagic:critical_strike.name=Critical Strike
upgrade.bloodmagic:jump.name=Jump Boost
# Chat

View file

@ -0,0 +1,32 @@
{
"parent": "item/generated",
"textures": {
"layer0": "bloodmagic:items/soul/monster_soul_raw"
},
"overrides": [
{
"predicate": {
"bloodmagic:will": 0.1
},
"model": "bloodmagic:item/soul/monster_soul_corrosive"
},
{
"predicate": {
"bloodmagic:will": 0.2
},
"model": "bloodmagic:item/soul/monster_soul_destructive"
},
{
"predicate": {
"bloodmagic:will": 0.3
},
"model": "bloodmagic:item/soul/monster_soul_vengeful"
},
{
"predicate": {
"bloodmagic:will": 0.4
},
"model": "bloodmagic:item/soul/monster_soul_steadfast"
}
]
}

View file

@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "bloodmagic:items/soul/monster_soul_corrosive"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "bloodmagic:items/soul/monster_soul_destructive"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "bloodmagic:items/soul/monster_soul_raw"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "bloodmagic:items/soul/monster_soul_steadfast"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "bloodmagic:items/soul/monster_soul_vengeful"
}
}

View file

@ -0,0 +1,70 @@
{
"parent": "item/generated",
"textures": {
"layer0": "bloodmagic:items/soul/sentient_sword_raw"
},
"overrides": [
{
"predicate": {
"bloodmagic:active": 1.0
},
"model": "bloodmagic:item/soul/sentient_sword_raw_active"
},
{
"predicate": {
"bloodmagic:will": 0.1,
"bloodmagic:active": 0.0
},
"model": "bloodmagic:item/soul/sentient_sword_corrosive"
},
{
"predicate": {
"bloodmagic:will": 0.1,
"bloodmagic:active": 1.0
},
"model": "bloodmagic:item/soul/sentient_sword_corrosive_active"
},
{
"predicate": {
"bloodmagic:will": 0.2,
"bloodmagic:active": 0.0
},
"model": "bloodmagic:item/soul/sentient_sword_destructive"
},
{
"predicate": {
"bloodmagic:will": 0.2,
"bloodmagic:active": 1.0
},
"model": "bloodmagic:item/soul/sentient_sword_destructive_active"
},
{
"predicate": {
"bloodmagic:will": 0.3,
"bloodmagic:active": 0.0
},
"model": "bloodmagic:item/soul/sentient_sword_vengeful"
},
{
"predicate": {
"bloodmagic:will": 0.3,
"bloodmagic:active": 1.0
},
"model": "bloodmagic:item/soul/sentient_sword_vengeful_active"
},
{
"predicate": {
"bloodmagic:will": 0.4,
"bloodmagic:active": 0.0
},
"model": "bloodmagic:item/soul/sentient_sword_steadfast"
},
{
"predicate": {
"bloodmagic:will": 0.4,
"bloodmagic:active": 1.0
},
"model": "bloodmagic:item/soul/sentient_sword_steadfast_active"
}
]
}

View file

@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "bloodmagic:items/soul/sentient_sword_corrosive"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "bloodmagic:items/soul/sentient_sword_corrosive_active"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "bloodmagic:items/soul/sentient_sword_destructive"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "bloodmagic:items/soul/sentient_sword_destructive_active"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "bloodmagic:items/soul/sentient_sword_raw_active"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "bloodmagic:items/soul/sentient_sword_steadfast"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "bloodmagic:items/soul/sentient_sword_steadfast_active"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "bloodmagic:items/soul/sentient_sword_vengeful"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "bloodmagic:items/soul/sentient_sword_vengeful_active"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 932 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 938 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 939 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 931 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 938 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 862 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 873 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 847 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 866 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 867 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 873 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 866 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 876 B

View file

@ -0,0 +1,3 @@
# simple descriptions as we go so there's *something* for everything
guide.bloodmagic:living_armor_upgrade_jump=Increases jump height. Decreases fall damage. Above level 2, it will also increase forward momentum while jumping.
guide.bloodmagic:living_armor_upgrade_arrow_protect=Decreases damage taken from projectiles.