Reworked ISpecialArmor to provide better functionality as requested by IC2 devs.

Armor can now be prioritized over other armor.
It can deal with damaging it's own itemstacks.
Also impkemented the ISpecialArmor.getArmorDisplay
This commit is contained in:
LexManos 2012-02-14 10:37:31 -08:00
parent f2b973e48a
commit d230b379f9
5 changed files with 328 additions and 126 deletions

View File

@ -5,23 +5,252 @@
package net.minecraft.src.forge;
public class ArmorProperties
import java.util.ArrayList;
import java.util.Arrays;
import net.minecraft.src.DamageSource;
import net.minecraft.src.EntityLiving;
import net.minecraft.src.EntityPlayer;
import net.minecraft.src.ItemArmor;
import net.minecraft.src.ItemStack;
public class ArmorProperties implements Comparable<ArmorProperties>
{
public double damageReduce = 0;
public int damageAbsorb = 0;
public int Priority = 0;
public int AbsorbMax = Integer.MAX_VALUE;
public double AbsorbRatio = 0;
public int Slot = 0;
private static final boolean DEBUG = false; //Only enable this if you wish to be spamed with debugging information.
//Left it in because I figured it'd be useful for modders developing custom armor.
public ArmorProperties () {}
/**
* Create an ArmorProperties describing the damage reduction.
*
* @param absorb Damage absorption. Removed from damage before damage
* reduction computation is applied.
* @param reduce Damage reduction, percentage of damage absorbed by
* armor where 1.0 =100%. A full set of diamond armor is 80%.
*/
public ArmorProperties (int absorb, double reduce)
public ArmorProperties(int priority, double ratio, int max)
{
damageReduce = reduce;
damageAbsorb = absorb;
Priority = priority;
AbsorbRatio = ratio;
AbsorbMax = max;
}
/**
* Gathers and applies armor reduction to damage being dealt to a entity.
*
* @param entity The Entity being damage
* @param inventory An array of armor items
* @param source The damage source type
* @param damage The total damage being done
* @return The left over damage that has not been absorbed by the armor
*/
public static int ApplyArmor(EntityLiving entity, ItemStack[] inventory, DamageSource source, double damage)
{
ArrayList<ArmorProperties> dmgVals = new ArrayList<ArmorProperties>();
if (DEBUG)
{
System.out.println("Start: " + damage);
}
for (int x = 0; x < inventory.length; x++)
{
ItemStack stack = inventory[x];
if (stack == null)
{
continue;
}
ArmorProperties prop = null;
if (stack.getItem() instanceof ISpecialArmor)
{
ISpecialArmor armor = (ISpecialArmor)stack.getItem();
prop = armor.getProperties(entity, stack, source, damage, x);
}
else if (stack.getItem() instanceof ItemArmor && !source.isUnblockable())
{
ItemArmor armor = (ItemArmor)stack.getItem();
prop = new ArmorProperties(0, armor.damageReduceAmount / 25D,
armor.getMaxDamage() - stack.getItemDamage());
}
if (prop != null)
{
prop.Slot = x;
dmgVals.add(prop);
}
}
if (dmgVals.size() > 0)
{
ArmorProperties[] props = dmgVals.toArray(new ArmorProperties[0]);
StanderdizeList(props, damage);
int level = props[0].Priority;
double ratio = 0;
double totalAbsorbed = 0;
for (ArmorProperties prop : props)
{
if (level != prop.Priority)
{
damage -= (damage * ratio);
ratio = 0;
level = prop.Priority;
}
ratio += prop.AbsorbRatio;
double absorb = damage * prop.AbsorbRatio;
if (absorb > 0)
{
ItemStack stack = inventory[prop.Slot];
if (stack.getItem() instanceof ISpecialArmor)
{
((ISpecialArmor)stack.getItem()).damageArmor(entity, stack, source, (int)(absorb < 1 ? 1 : (int)absorb), prop.Slot);
}
else
{
if (DEBUG)
{
System.out.println("Item: " + stack.toString() + " Absorbed: " + absorb + " Damaged: " + (int)(absorb < 1 ? 1 : (int)absorb));
}
stack.damageItem((int)(absorb < 1 ? 1 : (int)absorb), entity);
}
if (stack.stackSize <= 0)
{
if (entity instanceof EntityPlayer)
{
stack.onItemDestroyedByUse((EntityPlayer)entity);
}
inventory[prop.Slot] = null;
}
}
}
damage -= (damage * ratio);
}
if (DEBUG)
{
System.out.println("Return: " + (int)damage + " " + damage);
}
return (int)damage;
}
/**
* Sorts and standardizes the distribution of damage over armor.
*
* @param armor The armor information
* @param damage The total damage being received
*/
private static void StanderdizeList(ArmorProperties[] armor, double damage)
{
Arrays.sort(armor);
int start = 0;
double total = 0;
int priority = armor[0].Priority;
int pStart = 0;
boolean pChange = false;
boolean pFinished = false;
if (DEBUG)
{
for (ArmorProperties prop : armor)
System.out.println(prop);
System.out.println("========================");
}
for (int x = 0; x < armor.length; x++)
{
total += armor[x].AbsorbRatio;
if (x == armor.length - 1 || armor[x].Priority != priority)
{
if (armor[x].Priority != priority)
{
total -= armor[x].AbsorbRatio;
x--;
pChange = true;
}
if (total > 1)
{
for (int y = start; y <= x; y++)
{
double newRatio = armor[y].AbsorbRatio / total;
if (newRatio * damage > armor[y].AbsorbMax)
{
armor[y].AbsorbRatio = (double)armor[y].AbsorbMax / damage;
total = 0;
for (int z = pStart; z <= y; z++)
{
total += armor[z].AbsorbRatio;
}
start = y + 1;
x = y;
break;
}
else
{
armor[y].AbsorbRatio = newRatio;
pFinished = true;
}
}
if (pChange && pFinished)
{
damage -= (damage * total);
total = 0;
start = x + 1;
priority = armor[start].Priority;
pStart = start;
pChange = false;
pFinished = false;
if (damage <= 0)
{
for (int y = x + 1; y < armor.length; y++)
{
armor[y].AbsorbRatio = 0;
}
break;
}
}
}
else
{
for (int y = start; y <= x; y++)
{
total -= armor[y].AbsorbRatio;
if (damage * armor[y].AbsorbRatio > armor[y].AbsorbMax)
{
armor[y].AbsorbRatio = (double)armor[y].AbsorbMax / (double)damage;
}
total += armor[y].AbsorbRatio;
}
damage -= (damage * total);
total = 0;
if (x != armor.length - 1)
{
start = x + 1;
priority = armor[start].Priority;
pStart = start;
pChange = false;
if (damage <= 0)
{
for (int y = x + 1; y < armor.length; y++)
{
armor[y].AbsorbRatio = 0;
}
break;
}
}
}
}
}
if (DEBUG)
{
for (ArmorProperties prop : armor)
System.out.println(prop);
}
}
public int compareTo(ArmorProperties o)
{
if (o.Priority != Priority)
{
return o.Priority - Priority;
}
double left = ( AbsorbRatio == 0 ? 0 : AbsorbMax * 100.0D / AbsorbRatio);
double right = (o.AbsorbRatio == 0 ? 0 : o.AbsorbMax * 100.0D / o.AbsorbRatio);
return (int)(left - right);
}
public String toString()
{
return String.format("%d, %d, %f, %d", Priority, AbsorbMax, AbsorbRatio, (AbsorbRatio == 0 ? 0 : (int)(AbsorbMax * 100.0D / AbsorbRatio)));
}
}

View File

@ -6,6 +6,7 @@
package net.minecraft.src.forge;
import net.minecraft.src.DamageSource;
import net.minecraft.src.EntityLiving;
import net.minecraft.src.EntityPlayer;
import net.minecraft.src.ItemArmor;
import net.minecraft.src.ItemStack;
@ -19,30 +20,47 @@ import net.minecraft.src.ItemStack;
*/
public interface ISpecialArmor
{
/**
* Apply an armor effect to incoming damage. This should both compute
* the damage reduction properties of the armor against the incoming
* damage, and reduce the armor durability if appropriate. If the
* armor is destroyed, decrement the stack size of the ItemStack. It
* will then be cleaned up automatically.
*
* @param player The player wearing the armor.
* @param damageSource The source of the damage, which can be used to alter armor
* properties based on the type or source of damage.
* @param armor The ItemStack of the armor item itself. If you should
* need the index in damageArmor, use the armorType field in the item.
* @param damage The damage being applied to the armor.
*
*/
public ArmorProperties getProperties(EntityPlayer player, DamageSource damageSource, ItemStack armor, int damage);
/**
* Retrieves the modifiers to be used when calculating armor damage.
* Mods should return a new instance every time as the return values
* will be manipulated by the damage function.
*
* Armor will higher priority will have damage applied to them before
* lower priority ones. If there are multiple pieces of armor with the
* same priority, damage will be distributed between them based on there
* absorption ratio.
*
* @param entity The entity wearing the armor.
* @param armor The ItemStack of the armor item itself.
* @param source The source of the damage, which can be used to alter armor
* properties based on the type or source of damage.
* @param damage The total damage being applied to the entity
* @param slot The armor slot the item is in.
*
*/
public ArmorProperties getProperties(EntityLiving player, ItemStack armor, DamageSource source, double damage, int slot);
/**
* Get the displayed effective armor.
*
* @param player The player wearing the armor.
* @param armor The ItemStack of the armor item itself. If you should
* need the index in damageArmor, use the armorType field in the item.
* @return The number of armor points for display, 2 per shield.
*/
public abstract int getArmorDisplay(EntityPlayer player, ItemStack armor);
* Get the displayed effective armor.
*
* @param player The player wearing the armor.
* @param armor The ItemStack of the armor item itself.
* @param slot The armor slot the item is in.
* @return The number of armor points for display, 2 per shield.
*/
public abstract int getArmorDisplay(EntityPlayer player, ItemStack armor, int slot);
/**
* Applies damage to the ItemStack. The mod is responsible for reducing the
* item durability and stack size. If the stack is depleted it will be cleaned
* up automatically.
*
* @param entity The entity wearing the armor
* @param armor The ItemStack of the armor item itself.
* @param source The source of the damage, which can be used to alter armor
* properties based on the type or source of damage.
* @param damage The amount of damage being applied to the armor
* @param slot The armor slot the item is in.
*/
public abstract void damageArmor(EntityLiving entity, ItemStack stack, DamageSource source, int damage, int slot);
}

View File

@ -93,52 +93,14 @@
public boolean canHarvestBlock(Block block)
{
return inventory.canHarvestBlock(block);
@@ -768,8 +824,54 @@
@@ -768,8 +824,16 @@
{
i = 1 + i >> 1;
}
- i = applyArmorCalculations(damagesource, i);
- i = applyPotionDamageCalculations(damagesource, i);
+
+ int absorb = 0;
+ int reduce = 0;
+
+ for (int x = 0; x < inventory.armorInventory.length; x++)
+ {
+ ItemStack stack = inventory.armorInventory[x];
+ if (stack == null)
+ {
+ continue;
+ }
+
+ if (stack.getItem() instanceof ISpecialArmor)
+ {
+ ISpecialArmor armor = (ISpecialArmor)stack.getItem();
+ ArmorProperties props = armor.getProperties(this, damagesource, stack, i);
+ absorb += props.damageAbsorb;
+ reduce += props.damageReduce;
+ }
+ else if (stack.getItem() instanceof ItemArmor && !damagesource.isUnblockable())
+ {
+ reduce += ((ItemArmor)stack.getItem()).damageReduceAmount / 25.0;
+ stack.damageItem((i / 4 == 0 ? 1 : i / 4), this);
+ }
+
+ if (inventory.armorInventory[x] != null && stack.stackSize <= 0)
+ {
+ stack.onItemDestroyedByUse(this);
+ inventory.armorInventory[x] = null;
+ }
+ }
+
+ i -= absorb;
+ if (i <= 0)
+ {
+ return;
+ }
+
+ reduce = Math.min(25, 25 * reduce);
+ int damage = i * (25 - reduce) + carryoverDamage;
+ int damage = ArmorProperties.ApplyArmor(this, inventory.armorInventory, damagesource, (double)i * 25) + carryoverDamage;
+
+ carryoverDamage = damage % 25;
+ damage /= 25;
+ if (damage <= 0)
@ -150,7 +112,7 @@
addExhaustion(damagesource.getHungerDamage());
health -= i;
}
@@ -815,7 +917,9 @@
@@ -815,7 +879,9 @@
public void destroyCurrentEquippedItem()
{
@ -160,7 +122,7 @@
}
public double getYOffset()
@@ -834,6 +938,11 @@
@@ -834,6 +900,11 @@
public void attackTargetEntityWithCurrentItem(Entity entity)
{
@ -172,7 +134,7 @@
int i = inventory.getDamageVsEntity(entity);
if (isPotionActive(Potion.damageBoost))
{
@@ -947,6 +1056,11 @@
@@ -947,6 +1018,11 @@
public EnumStatus sleepInBedAt(int i, int j, int k)
{

View File

@ -0,0 +1,31 @@
--- ../src_base/minecraft/net/minecraft/src/GuiIngame.java 0000-00-00 00:00:00.000000000 -0000
+++ ../src_work/minecraft/net/minecraft/src/GuiIngame.java 0000-00-00 00:00:00.000000000 -0000
@@ -5,6 +5,7 @@
import java.util.Random;
import net.minecraft.client.Minecraft;
import org.lwjgl.opengl.GL11;
+import net.minecraft.src.forge.ISpecialArmor;
public class GuiIngame extends Gui
{
@@ -106,7 +107,19 @@
}
int k8 = l - 39;
int j9 = k8 - 10;
- int i10 = mc.thePlayer.getTotalArmorValue();
+ int i10 = 0;
+ for (int x = 0; x < mc.thePlayer.inventory.armorInventory.length; x++)
+ {
+ ItemStack stack = mc.thePlayer.inventory.armorInventory[x];
+ if (stack != null && stack.getItem() instanceof ISpecialArmor)
+ {
+ i10 += ((ISpecialArmor)stack.getItem()).getArmorDisplay(mc.thePlayer, stack, x);
+ }
+ else if (stack != null && stack.getItem() instanceof ItemArmor)
+ {
+ i10 += ((ItemArmor)stack.getItem()).damageReduceAmount;
+ }
+ }
int j10 = -1;
if (mc.thePlayer.isPotionActive(Potion.regeneration))
{

View File

@ -103,52 +103,14 @@
public boolean canHarvestBlock(Block block)
{
return inventory.canHarvestBlock(block);
@@ -711,8 +770,54 @@
@@ -711,8 +770,16 @@
{
i = 1 + i >> 1;
}
- i = applyArmorCalculations(damagesource, i);
- i = applyPotionDamageCalculations(damagesource, i);
+
+ int absorb = 0;
+ int reduce = 0;
+
+ for (int x = 0; x < inventory.armorInventory.length; x++)
+ {
+ ItemStack stack = inventory.armorInventory[x];
+ if (stack == null)
+ {
+ continue;
+ }
+
+ if (stack.getItem() instanceof ISpecialArmor)
+ {
+ ISpecialArmor armor = (ISpecialArmor)stack.getItem();
+ ArmorProperties props = armor.getProperties(this, damagesource, stack, i);
+ absorb += props.damageAbsorb;
+ reduce += props.damageReduce;
+ }
+ else if (stack.getItem() instanceof ItemArmor && !damagesource.isUnblockable())
+ {
+ reduce += ((ItemArmor)stack.getItem()).damageReduceAmount / 25.0;
+ stack.damageItem((i / 4 == 0 ? 1 : i / 4), this);
+ }
+
+ if (inventory.armorInventory[x] != null && stack.stackSize <= 0)
+ {
+ stack.onItemDestroyedByUse(this);
+ inventory.armorInventory[x] = null;
+ }
+ }
+ int damage = ArmorProperties.ApplyArmor(this, inventory.armorInventory, damagesource, (double)i * 25) + carryoverDamage;
+
+ i -= absorb;
+ if (i <= 0)
+ {
+ return;
+ }
+
+ reduce = Math.min(25, 25 * reduce);
+ int damage = i * (25 - reduce) + carryoverDamage;
+ carryoverDamage = damage % 25;
+ damage /= 25;
+ if (damage <= 0)
@ -160,7 +122,7 @@
addExhaustion(damagesource.getHungerDamage());
health -= i;
}
@@ -758,7 +863,9 @@
@@ -758,7 +825,9 @@
public void destroyCurrentEquippedItem()
{
@ -170,7 +132,7 @@
}
public double getYOffset()
@@ -777,6 +884,11 @@
@@ -777,6 +846,11 @@
public void attackTargetEntityWithCurrentItem(Entity entity)
{
@ -182,7 +144,7 @@
int i = inventory.getDamageVsEntity(entity);
if (isPotionActive(Potion.damageBoost))
{
@@ -884,6 +996,11 @@
@@ -884,6 +958,11 @@
public EnumStatus sleepInBedAt(int i, int j, int k)
{