package minefantasy.system; import minefantasy.api.armour.EnumArmourClass; import minefantasy.api.armour.IArmourClass; import minefantasy.api.tactic.ISpecialSenses; import minefantasy.api.tactic.IStealthArmour; import minefantasy.api.weapon.IHiddenItem; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.EnumCreatureAttribute; import net.minecraft.entity.monster.EntityMob; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.EnumArmorMaterial; import net.minecraft.item.Item; import net.minecraft.item.ItemArmor; import net.minecraft.item.ItemStack; import net.minecraft.potion.Potion; public class TacticalManager { public static boolean isFlankedBy(Entity attacker, EntityLivingBase defender, float angle) { float att = getAttackAngle(attacker, defender); return att > 270 - (angle/2) && att < 270 + (angle/2); } public static float getAttackAngle(Entity attacker, EntityLivingBase defender) { float attackedAtYaw = 90.0F; if (attacker != null) { double d = attacker.posX - defender.posX; double d1; for (d1 = attacker.posZ - defender.posZ; d * d + d1 * d1 < 0.0001D; d1 = (Math .random() - Math.random()) * 0.01D) { d = (Math.random() - Math.random()) * 0.01D; } attackedAtYaw = (float) ((Math.atan2(d1, d) * 180D) / Math.PI) - defender.rotationYaw; while (attackedAtYaw > 360) attackedAtYaw = attackedAtYaw - 360; while (attackedAtYaw < 0) attackedAtYaw = attackedAtYaw + 360; } return attackedAtYaw; } /** * @param target The fellow trying to hide * @param observer who is looking * @return true if the observer can see the target */ public static boolean isDetected(Entity target, Entity observer) { /* if(targeter != null && target != null) { if(targeter instanceof EntityLiving) { if(((EntityLiving)targeter).getAttackTarget() != null && ((EntityLiving)targeter).getAttackTarget() == target) return true; } } */ if(observer instanceof EntityLiving) { if(((EntityLiving)observer).hurtResistantTime > 0) { return true; } } boolean sound = getAudioSound(target, observer) > getHearing(observer); boolean seen = getVisibility(target, observer) > getSight(observer); return sound || seen; } public static int getVisibility(Entity target, Entity targeter) { int r = 100; //BEHIND if(isFlankedBy(target, (EntityLivingBase)targeter, 360-(getArc(targeter)*2))) { return 0; } //Direct viewing else if(!isFlankedBy(target, (EntityLivingBase)targeter, 360-getArc(targeter))) { r += 10; } //DISTANCE int range = (int)target.getDistanceToEntity(targeter); if(range > 10) r -= (range - 10); if(range < 0.25F) { return 100; } //DARKNESS float light = target.worldObj.getBlockLightValue((int)target.posX, (int)target.posY, (int)target.posZ); if(light> 24) light = 24; float multi = 4F; if(target instanceof EntityLiving) { multi *= modLight((EntityLiving)target); } r -= (24-light)*multi; if(isInvisible(target)) r = 0; return r; } private static boolean isInvisible(Entity target) { if(target instanceof EntityLiving) { EntityLiving live = (EntityLiving)target; if(live.getActivePotionEffect(Potion.invisibility) != null) { for(int a = 0; a < 5; a ++) { if(live.getCurrentItemOrArmor(a) != null) { if(live.getCurrentItemOrArmor(a).getItem() instanceof IHiddenItem) { if(!((IHiddenItem)live.getCurrentItemOrArmor(a).getItem()).doesHide()) { return false; } } else if(live.getCurrentItemOrArmor(a).getItem() instanceof IStealthArmour) { if(!((IStealthArmour)live.getCurrentItemOrArmor(a).getItem()).canTurnInvisible()) { return false; } } else return false; } } return true; } } return false; } public static int getAudioSound(Entity target, Entity targeter) { int r = 0; //SNEAK if(!isQuietSteps(target) && getSpeed(target) > 0) { r += 50; } //Sprint if(target.isSprinting()) { r += 50; } //ARMOUR EFFECTS //ARMOUR int spd = r; if(target instanceof EntityPlayer) spd = (int)getAudioMod((EntityPlayer)target, r); if(spd < r) r = spd; if(getSpeed(target) > 0) { if(spd > r)r = spd; //WATER if(target.isInWater()) { r += 10; } } //DISTANCE int range = (int)target.getDistanceToEntity(targeter); if(range > 2) r /= (range/2); if(target instanceof EntityLiving) { r = modSound(r, (EntityLiving)target); } return r; } private static boolean isQuietSteps(Entity target) { if(target instanceof EntityLivingBase) { EntityLivingBase live = (EntityLivingBase)target; if(live.getCurrentItemOrArmor(4) != null) { if(live.getCurrentItemOrArmor(4).getItem() instanceof IStealthArmour) { if(((IStealthArmour)live.getCurrentItemOrArmor(4).getItem()).quietRun()) { return !target.isSprinting(); } } } } return target.isSneaking(); } private static double getSpeed(Entity target) { double x = target.posX - target.lastTickPosX; double y = target.posZ - target.lastTickPosZ; if(y < 0) y = -y; if(x < 0) x = -x; return Math.hypot(x, y); } public static double getAudioMod(EntityPlayer player, int r) { int r1 = r; EnumArmourClass AC0 = getClassInSlot(player, 0); r += (double)AC0.getSoundMod(0); EnumArmourClass AC1 = getClassInSlot(player, 1); r += (double)AC1.getSoundMod(1); EnumArmourClass AC2 = getClassInSlot(player, 2); r += (double)AC2.getSoundMod(2); EnumArmourClass AC3 = getClassInSlot(player, 3); r += (double)AC3.getSoundMod(3); return (double)r; } public static EnumArmourClass getClassInSlot(EntityPlayer player, int i) { return getClassFor(armourInSlot(player, i)); } public static EnumArmourClass getClassFor(ItemStack armour) { if(armour == null) { return EnumArmourClass.UNARMOURED; } EnumArmourClass AC = EnumArmourClass.HEAVY; if(armour.itemID == Item.helmetLeather.itemID || armour.itemID == Item.plateLeather.itemID || armour.itemID == Item.legsLeather.itemID || armour.itemID == Item.bootsLeather.itemID) { AC = EnumArmourClass.LIGHT; } else if(armour.getItem().getClass().getName().endsWith("MoCItemArmor")) { AC = EnumArmourClass.LIGHT; } else if(armour.itemID == Item.helmetChain.itemID || armour.itemID == Item.plateChain.itemID || armour.itemID == Item.legsChain.itemID || armour.itemID == Item.bootsChain.itemID) { AC = EnumArmourClass.MEDIUM; } else if(armour.getItem() instanceof IArmourClass) { AC = ((IArmourClass)armour.getItem()).getArmourClass(); } else { if(armour.getItem() != null && armour.getItem() instanceof ItemArmor) { EnumArmorMaterial material = ((ItemArmor)armour.getItem()).getArmorMaterial(); AC = getClassOf(material, AC); } } AC = minefantasy.api.armour.ArmourWeightClass.getClassFor(armour, AC); return AC; } private static EnumArmourClass getClassOf(EnumArmorMaterial material, EnumArmourClass AC) { return AC; } public static int getHearing(Entity entity) { if(entity instanceof ISpecialSenses) { return((ISpecialSenses)entity).getSight(); } if(entity instanceof EntityMob) { if(((EntityMob)entity).getCreatureAttribute() == EnumCreatureAttribute.UNDEAD) { return 10; } } return 5; } private static ItemStack armourInSlot(EntityPlayer player, int i) { return player.inventory.armorItemInSlot(i); } public static int getSight(Entity entity) { if(entity instanceof ISpecialSenses) { return((ISpecialSenses)entity).getSight(); } return 20; } private static int getArc(Entity entity) { if(entity instanceof ISpecialSenses) { return((ISpecialSenses)entity).getViewingArc(); } return 90; } public static float getSoundModForItem(Item item) { if(item == null) return 1.0F; if(item instanceof IStealthArmour) { return ((IStealthArmour)item).noiseReduction(); } return 1.0F; } public static float getSightModForItem(Item item) { if(item == null) return 1.0F; if(item instanceof IStealthArmour) { return ((IStealthArmour)item).darknessAmplifier(); } return 1.0F; } public static float modLight(EntityLiving live) { float tot = 0.0F; for(int a = 0; a < 4; a ++) { ItemStack armour = live.getCurrentItemOrArmor(a); if(armour == null) { tot += 1.0F; } else { tot += getSightModForItem(armour.getItem()); } } return tot/4; } public static int modSound(int sound, EntityLiving live) { float tot = 0.0F; for(int a = 0; a < 4; a ++) { ItemStack armour = live.getCurrentItemOrArmor(a); if(armour == null) { tot += 1.0F; } else { tot += getSoundModForItem(armour.getItem()); } } return (int)(tot/4); } public static boolean canBackstab(EntityLivingBase attacker, EntityLivingBase target) { return isFlankedBy(target, (EntityLivingBase)attacker, 90); } }