mirror of
https://github.com/KAMKEEL/CustomNPC-Plus.git
synced 2026-11-12 00:17:27 +00:00
706 lines
21 KiB
Java
706 lines
21 KiB
Java
package noppes.npcs.roles;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
import java.util.Iterator;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Random;
|
|
import java.util.TreeMap;
|
|
import java.util.UUID;
|
|
import java.util.Map.Entry;
|
|
|
|
import com.google.common.collect.HashMultimap;
|
|
|
|
import cpw.mods.fml.common.ObfuscationReflectionHelper;
|
|
import net.minecraft.entity.Entity;
|
|
import net.minecraft.entity.SharedMonsterAttributes;
|
|
import net.minecraft.entity.ai.attributes.AttributeModifier;
|
|
import net.minecraft.entity.ai.attributes.BaseAttributeMap;
|
|
import net.minecraft.entity.ai.attributes.IAttributeInstance;
|
|
import net.minecraft.entity.player.EntityPlayer;
|
|
import net.minecraft.init.Blocks;
|
|
import net.minecraft.init.Items;
|
|
import net.minecraft.item.Item;
|
|
import net.minecraft.item.ItemArmor;
|
|
import net.minecraft.item.ItemBow;
|
|
import net.minecraft.item.ItemFood;
|
|
import net.minecraft.item.ItemStack;
|
|
import net.minecraft.item.ItemSword;
|
|
import net.minecraft.item.ItemArmor.ArmorMaterial;
|
|
import net.minecraft.nbt.NBTTagCompound;
|
|
import net.minecraft.nbt.NBTTagList;
|
|
import net.minecraft.util.DamageSource;
|
|
import net.minecraft.util.MathHelper;
|
|
import net.minecraft.util.Vec3;
|
|
import noppes.npcs.CustomNpcs;
|
|
import noppes.npcs.NoppesUtilServer;
|
|
import noppes.npcs.NpcMiscInventory;
|
|
import noppes.npcs.constants.EnumAnimation;
|
|
import noppes.npcs.constants.EnumCompanionJobs;
|
|
import noppes.npcs.constants.EnumCompanionStage;
|
|
import noppes.npcs.constants.EnumCompanionTalent;
|
|
import noppes.npcs.constants.EnumGuiType;
|
|
import noppes.npcs.controllers.PlayerData;
|
|
import noppes.npcs.controllers.PlayerDataController;
|
|
import noppes.npcs.entity.EntityCustomNpc;
|
|
import noppes.npcs.entity.EntityNPCInterface;
|
|
import noppes.npcs.roles.companion.CompanionFarmer;
|
|
import noppes.npcs.roles.companion.CompanionFoodStats;
|
|
import noppes.npcs.roles.companion.CompanionGuard;
|
|
import noppes.npcs.roles.companion.CompanionJobInterface;
|
|
import noppes.npcs.roles.companion.CompanionTrader;
|
|
|
|
public class RoleCompanion extends RoleInterface {
|
|
public NpcMiscInventory inventory;
|
|
public String uuid = "";
|
|
public String ownerName = "";
|
|
public Map<EnumCompanionTalent, Integer> talents = new TreeMap<EnumCompanionTalent, Integer>();
|
|
|
|
public boolean canAge = true;
|
|
public long ticksActive = 0;
|
|
public EnumCompanionStage stage = EnumCompanionStage.FULLGROWN;
|
|
|
|
public EntityPlayer owner = null;
|
|
public int companionID;
|
|
|
|
public EnumCompanionJobs job = EnumCompanionJobs.NONE;
|
|
public CompanionJobInterface jobInterface = null;
|
|
|
|
public boolean hasInv = true;
|
|
public boolean defendOwner = true;
|
|
|
|
public CompanionFoodStats foodstats = new CompanionFoodStats();
|
|
private int eatingTicks = 20;
|
|
private ItemStack eating = null;
|
|
private int eatingDelay = 00;
|
|
|
|
public int currentExp = 0;
|
|
|
|
public RoleCompanion(EntityNPCInterface npc) {
|
|
super(npc);
|
|
inventory = new NpcMiscInventory(12);
|
|
}
|
|
|
|
@Override
|
|
public boolean aiShouldExecute() {
|
|
EntityPlayer prev = owner;
|
|
owner = getOwner();
|
|
if(jobInterface != null && jobInterface.isSelfSufficient())
|
|
return true;
|
|
|
|
if(owner == null && !uuid.isEmpty()){
|
|
npc.isDead = true;
|
|
}
|
|
else if(prev != owner && owner != null){
|
|
ownerName = owner.getDisplayName();
|
|
PlayerData data = PlayerDataController.instance.getPlayerData(owner);
|
|
if(data.companionID != companionID){
|
|
npc.isDead = true;
|
|
}
|
|
}
|
|
return owner != null;
|
|
}
|
|
|
|
@Override
|
|
public void aiUpdateTask() {
|
|
if(owner != null && (jobInterface == null || !jobInterface.isSelfSufficient()))
|
|
foodstats.onUpdate(npc);
|
|
if(foodstats.getFoodLevel() >= 18){
|
|
npc.stats.healthRegen = 0;
|
|
npc.stats.combatRegen = 0;
|
|
}
|
|
if(foodstats.needFood() && isSitting()){
|
|
if(eatingDelay > 0){
|
|
eatingDelay--;
|
|
return;
|
|
}
|
|
|
|
ItemStack prev = eating;
|
|
eating = getFood();
|
|
|
|
if(prev != null && eating == null)
|
|
npc.setRoleDataWatcher("");
|
|
|
|
if(prev == null && eating != null){
|
|
npc.setRoleDataWatcher("eating");
|
|
eatingTicks = 20;
|
|
}
|
|
|
|
if(isEating()){
|
|
doEating();
|
|
}
|
|
|
|
}
|
|
else if(eating != null && !isSitting()){
|
|
eating = null;
|
|
eatingDelay = 20;
|
|
npc.setRoleDataWatcher("");
|
|
}
|
|
|
|
ticksActive++;
|
|
if(canAge && stage != EnumCompanionStage.FULLGROWN){
|
|
if(stage == EnumCompanionStage.BABY && ticksActive > EnumCompanionStage.CHILD.matureAge){
|
|
matureTo(EnumCompanionStage.CHILD);
|
|
}
|
|
else if(stage == EnumCompanionStage.CHILD && ticksActive > EnumCompanionStage.TEEN.matureAge){
|
|
matureTo(EnumCompanionStage.TEEN);
|
|
}
|
|
else if(stage == EnumCompanionStage.TEEN && ticksActive > EnumCompanionStage.ADULT.matureAge){
|
|
matureTo(EnumCompanionStage.ADULT);
|
|
}
|
|
else if(stage == EnumCompanionStage.ADULT && ticksActive > EnumCompanionStage.FULLGROWN.matureAge){
|
|
matureTo(EnumCompanionStage.FULLGROWN);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void clientUpdate() {
|
|
if(npc.getRoleDataWatcher().equals("eating")){
|
|
eating = getFood();
|
|
|
|
if(isEating()){
|
|
doEating();
|
|
}
|
|
}
|
|
else if(eating != null){
|
|
eating = null;
|
|
}
|
|
|
|
}
|
|
private void doEating(){
|
|
if(npc.worldObj.isRemote){
|
|
Random rand = npc.getRNG();
|
|
for (int j = 0; j < 2; ++j){
|
|
Vec3 vec3 = Vec3.createVectorHelper(((double)rand.nextFloat() - 0.5D) * 0.1D, Math.random() * 0.1D + 0.1D, 0.0D);
|
|
vec3.rotateAroundX(-npc.rotationPitch * (float)Math.PI / 180.0F);
|
|
vec3.rotateAroundY(-npc.renderYawOffset * (float)Math.PI / 180.0F);
|
|
Vec3 vec31 = Vec3.createVectorHelper(((double)rand.nextFloat() - 0.5D) * 0.3D, (double)(-rand.nextFloat()) * 0.6D - 0.3D, npc.width / 2 + 0.1);
|
|
vec31.rotateAroundX(-npc.rotationPitch * (float)Math.PI / 180.0F);
|
|
vec31.rotateAroundY(-npc.renderYawOffset * (float)Math.PI / 180.0F);
|
|
vec31 = vec31.addVector(npc.posX, npc.posY + (double)npc.height + 0.1, npc.posZ);
|
|
String s = "iconcrack_" + Item.getIdFromItem(eating.getItem());
|
|
|
|
if (eating.getHasSubtypes()){
|
|
s = s + "_" + eating.getItemDamage();
|
|
}
|
|
|
|
npc.worldObj.spawnParticle(s, vec31.xCoord, vec31.yCoord, vec31.zCoord, vec3.xCoord, vec3.yCoord + 0.0D, vec3.zCoord);
|
|
}
|
|
}
|
|
else{
|
|
eatingTicks--;
|
|
|
|
if(eatingTicks <= 0){
|
|
if(inventory.decrStackSize(eating, 1)){
|
|
ItemFood food = (ItemFood) eating.getItem();
|
|
foodstats.onFoodEaten(food, eating);
|
|
npc.playSound("random.burp", 0.5F, npc.getRNG().nextFloat() * 0.1F + 0.9F);
|
|
}
|
|
eatingDelay = 20;
|
|
npc.setRoleDataWatcher("");
|
|
eating = null;
|
|
}
|
|
else if(eatingTicks > 3 && eatingTicks % 2 == 0){
|
|
Random rand = npc.getRNG();
|
|
npc.playSound("random.eat", 0.5F + 0.5F * rand.nextInt(2), (rand.nextFloat() - rand.nextFloat()) * 0.2F + 1.0F);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void matureTo(EnumCompanionStage stage){
|
|
this.stage = stage;
|
|
EntityCustomNpc npc = (EntityCustomNpc) this.npc;
|
|
npc.ai.animationType = stage.animation;
|
|
if(stage == EnumCompanionStage.BABY){
|
|
npc.modelData.arms.setScale(0.5f, 0.5f, 0.5f);
|
|
npc.modelData.legs.setScale(0.5f, 0.5f, 0.5f);
|
|
npc.modelData.body.setScale(0.5f, 0.5f, 0.5f);
|
|
npc.modelData.head.setScale(0.7f, 0.7f, 0.7f);
|
|
|
|
npc.ai.onAttack = 1;
|
|
npc.ai.setWalkingSpeed(3);
|
|
if(!talents.containsKey(EnumCompanionTalent.INVENTORY))
|
|
talents.put(EnumCompanionTalent.INVENTORY, 0);
|
|
}
|
|
if(stage == EnumCompanionStage.CHILD){
|
|
npc.modelData.arms.setScale(0.6f, 0.6f, 0.6f);
|
|
npc.modelData.legs.setScale(0.6f, 0.6f, 0.6f);
|
|
npc.modelData.body.setScale(0.6f, 0.6f, 0.6f);
|
|
npc.modelData.head.setScale(0.8f, 0.8f, 0.8f);
|
|
|
|
npc.ai.onAttack = 0;
|
|
npc.ai.setWalkingSpeed(4);
|
|
if(!talents.containsKey(EnumCompanionTalent.SWORD))
|
|
talents.put(EnumCompanionTalent.SWORD, 0);
|
|
}
|
|
if(stage == EnumCompanionStage.TEEN){
|
|
npc.modelData.arms.setScale(0.8f, 0.8f, 0.8f);
|
|
npc.modelData.legs.setScale(0.8f, 0.8f, 0.8f);
|
|
npc.modelData.body.setScale(0.8f, 0.8f, 0.8f);
|
|
npc.modelData.head.setScale(0.9f, 0.9f, 0.9f);
|
|
|
|
npc.ai.onAttack = 0;
|
|
npc.ai.setWalkingSpeed(5);
|
|
if(!talents.containsKey(EnumCompanionTalent.ARMOR))
|
|
talents.put(EnumCompanionTalent.ARMOR, 0);
|
|
}
|
|
if(stage == EnumCompanionStage.ADULT || stage == EnumCompanionStage.FULLGROWN){
|
|
npc.modelData.arms.setScale(1f, 1f, 1f);
|
|
npc.modelData.legs.setScale(1f, 1f, 1f);
|
|
npc.modelData.body.setScale(1f, 1f, 1f);
|
|
npc.modelData.head.setScale(1f, 1f, 1f);
|
|
|
|
npc.ai.onAttack = 0;
|
|
npc.ai.setWalkingSpeed(5);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public NBTTagCompound writeToNBT(NBTTagCompound compound) {
|
|
compound.setTag("CompanionInventory", inventory.getToNBT());
|
|
compound.setString("CompanionOwner", uuid);
|
|
compound.setString("CompanionOwnerName", ownerName);
|
|
compound.setInteger("CompanionID", companionID);
|
|
|
|
compound.setInteger("CompanionStage", stage.ordinal());
|
|
compound.setInteger("CompanionExp", currentExp);
|
|
compound.setBoolean("CompanionCanAge", canAge);
|
|
compound.setLong("CompanionAge", ticksActive);
|
|
|
|
compound.setBoolean("CompanionHasInv", hasInv);
|
|
compound.setBoolean("CompanionDefendOwner", defendOwner);
|
|
|
|
foodstats.writeNBT(compound);
|
|
|
|
compound.setInteger("CompanionJob", job.ordinal());
|
|
if(jobInterface != null)
|
|
compound.setTag("CompanionJobData", jobInterface.getNBT());
|
|
|
|
NBTTagList list = new NBTTagList();
|
|
for(EnumCompanionTalent talent : talents.keySet()){
|
|
NBTTagCompound c = new NBTTagCompound();
|
|
c.setInteger("Talent", talent.ordinal());
|
|
c.setInteger("Exp", talents.get(talent));
|
|
list.appendTag(c);
|
|
}
|
|
compound.setTag("CompanionTalents", list);
|
|
return compound;
|
|
}
|
|
|
|
@Override
|
|
public void readFromNBT(NBTTagCompound compound) {
|
|
inventory.setFromNBT(compound.getCompoundTag("CompanionInventory"));
|
|
uuid = compound.getString("CompanionOwner");
|
|
ownerName = compound.getString("CompanionOwnerName");
|
|
companionID = compound.getInteger("CompanionID");
|
|
|
|
stage = EnumCompanionStage.values()[compound.getInteger("CompanionStage")];
|
|
currentExp = compound.getInteger("CompanionExp");
|
|
canAge = compound.getBoolean("CompanionCanAge");
|
|
ticksActive = compound.getLong("CompanionAge");
|
|
|
|
hasInv = compound.getBoolean("CompanionHasInv");
|
|
defendOwner = compound.getBoolean("CompanionDefendOwner");
|
|
|
|
foodstats.readNBT(compound);
|
|
|
|
NBTTagList list = compound.getTagList("CompanionTalents", 10);
|
|
Map<EnumCompanionTalent, Integer> talents = new TreeMap<EnumCompanionTalent, Integer>();
|
|
for(int i = 0; i < list.tagCount(); i++){
|
|
NBTTagCompound c = list.getCompoundTagAt(i);
|
|
EnumCompanionTalent talent = EnumCompanionTalent.values()[c.getInteger("Talent")];
|
|
talents.put(talent, c.getInteger("Exp"));
|
|
}
|
|
this.talents = talents;
|
|
|
|
setJob(compound.getInteger("CompanionJob"));
|
|
if(jobInterface != null)
|
|
jobInterface.setNBT(compound.getCompoundTag("CompanionJobData"));
|
|
setStats();
|
|
}
|
|
|
|
private void setJob(int i) {
|
|
job = EnumCompanionJobs.values()[i];
|
|
if(job == EnumCompanionJobs.SHOP)
|
|
jobInterface = new CompanionTrader();
|
|
else if(job == EnumCompanionJobs.FARMER)
|
|
jobInterface = new CompanionFarmer();
|
|
else if(job == EnumCompanionJobs.GUARD)
|
|
jobInterface = new CompanionGuard();
|
|
else
|
|
jobInterface = null;
|
|
|
|
if(jobInterface != null)
|
|
jobInterface.npc = npc;
|
|
}
|
|
|
|
@Override
|
|
public void interact(EntityPlayer player) {
|
|
if(player != null && job == EnumCompanionJobs.SHOP)
|
|
((CompanionTrader)jobInterface).interact(player);
|
|
if(player != owner || !npc.isEntityAlive() || npc.isAttacking())
|
|
return;
|
|
if(player.isSneaking()){
|
|
openGui(player);
|
|
}
|
|
else{
|
|
setSitting(!isSitting());
|
|
}
|
|
}
|
|
|
|
public int getTotalLevel(){
|
|
int level = 0;
|
|
for(EnumCompanionTalent talent : talents.keySet())
|
|
level += this.getTalentLevel(talent);
|
|
return level;
|
|
}
|
|
|
|
public int getMaxExp(){
|
|
return 500 + getTotalLevel() * 200;
|
|
}
|
|
|
|
public void addExp(int exp){
|
|
if(canAddExp(exp))
|
|
this.currentExp += exp;
|
|
}
|
|
|
|
public boolean canAddExp(int exp){
|
|
int newExp = this.currentExp + exp;
|
|
return newExp >= 0 && newExp < getMaxExp();
|
|
}
|
|
|
|
public void gainExp(int chance){
|
|
if(npc.getRNG().nextInt(chance) == 0)
|
|
addExp(1);
|
|
}
|
|
|
|
private void openGui(EntityPlayer player){
|
|
NoppesUtilServer.sendOpenGui(player, EnumGuiType.Companion, npc);
|
|
}
|
|
|
|
public EntityPlayer getOwner(){
|
|
if(uuid == null || uuid.isEmpty())
|
|
return null;
|
|
try{
|
|
UUID id = UUID.fromString(uuid);
|
|
if(id != null){
|
|
return NoppesUtilServer.getPlayer(id);
|
|
}
|
|
}
|
|
catch(IllegalArgumentException ex){
|
|
|
|
}
|
|
return null;
|
|
}
|
|
|
|
|
|
public void setOwner(EntityPlayer player) {
|
|
uuid = player.getUniqueID().toString();
|
|
}
|
|
|
|
|
|
public boolean hasTalent(EnumCompanionTalent talent) {
|
|
return getTalentLevel(talent) > 0;
|
|
}
|
|
|
|
public int getTalentLevel(EnumCompanionTalent talent){
|
|
if(!talents.containsKey(talent))
|
|
return 0;
|
|
|
|
int exp = talents.get(talent);
|
|
if(exp >= 5000)
|
|
return 5;
|
|
if(exp >= 3000)
|
|
return 4;
|
|
if(exp >= 1700)
|
|
return 3;
|
|
if(exp >= 1000)
|
|
return 2;
|
|
if(exp >= 400)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
public Integer getNextLevel(EnumCompanionTalent talent) {
|
|
if(!talents.containsKey(talent))
|
|
return 0;
|
|
int exp = talents.get(talent);
|
|
if(exp < 400)
|
|
return 400;
|
|
if(exp < 1000)
|
|
return 700;
|
|
if(exp < 1700)
|
|
return 1700;
|
|
if(exp < 3000)
|
|
return 3000;
|
|
return 5000;
|
|
}
|
|
|
|
public void levelSword(){
|
|
if(!talents.containsKey(EnumCompanionTalent.SWORD))
|
|
return;
|
|
}
|
|
public void levelTalent(EnumCompanionTalent talent, int exp){
|
|
if(!talents.containsKey(EnumCompanionTalent.SWORD))
|
|
return;
|
|
talents.put(talent, exp + talents.get(talent));
|
|
}
|
|
|
|
public int getExp(EnumCompanionTalent talent) {
|
|
if(talents.containsKey(talent))
|
|
return talents.get(talent);
|
|
return -1;
|
|
}
|
|
|
|
public void setExp(EnumCompanionTalent talent, int exp) {
|
|
talents.put(talent, exp);
|
|
}
|
|
|
|
private boolean isWeapon(ItemStack item) {
|
|
if(item == null || item.getItem() == null)
|
|
return false;
|
|
return item.getItem() instanceof ItemSword ||
|
|
item.getItem() instanceof ItemBow ||
|
|
item.getItem() == Item.getItemFromBlock(Blocks.cobblestone);
|
|
}
|
|
|
|
public boolean canWearWeapon(ItemStack item){
|
|
if(item == null || item.getItem() == null)
|
|
return false;
|
|
|
|
if(item.getItem() instanceof ItemSword)
|
|
return canWearSword(item);
|
|
|
|
if(item.getItem() instanceof ItemBow)
|
|
return this.getTalentLevel(EnumCompanionTalent.RANGED) > 2;
|
|
|
|
if(item.getItem() == Item.getItemFromBlock(Blocks.cobblestone))
|
|
return this.getTalentLevel(EnumCompanionTalent.RANGED) > 1;
|
|
|
|
return false;
|
|
}
|
|
|
|
public boolean canWearArmor(ItemStack item){
|
|
int level = getTalentLevel(EnumCompanionTalent.ARMOR);
|
|
if(item == null || !(item.getItem() instanceof ItemArmor) || level <= 0)
|
|
return false;
|
|
|
|
if(level >= 5)
|
|
return true;
|
|
|
|
ItemArmor armor = (ItemArmor) item.getItem();
|
|
int reduction = ObfuscationReflectionHelper.getPrivateValue(ArmorMaterial.class, armor.getArmorMaterial(), 5);
|
|
if(reduction <= 5 && level >= 1)
|
|
return true;
|
|
if(reduction <= 7 && level >= 2)
|
|
return true;
|
|
if(reduction <= 15 && level >= 3)
|
|
return true;
|
|
if(reduction <= 33 && level >= 4)
|
|
return true;
|
|
return false;
|
|
}
|
|
public boolean canWearSword(ItemStack item){
|
|
int level = getTalentLevel(EnumCompanionTalent.SWORD);
|
|
if(item == null || !(item.getItem() instanceof ItemSword) || level <= 0)
|
|
return false;
|
|
if(level >= 5)
|
|
return true;
|
|
return getSwordDamage(item) - level < 4;
|
|
}
|
|
|
|
private double getSwordDamage(ItemStack item){
|
|
if(item == null || !(item.getItem() instanceof ItemSword))
|
|
return 0;
|
|
HashMultimap map = (HashMultimap) item.getAttributeModifiers();
|
|
Iterator iterator = map.entries().iterator();
|
|
while (iterator.hasNext())
|
|
{
|
|
Entry entry = (Entry)iterator.next();
|
|
if(entry.getKey().equals(SharedMonsterAttributes.attackDamage.getAttributeUnlocalizedName())){
|
|
AttributeModifier mod = (AttributeModifier) entry.getValue();
|
|
return mod.getAmount();
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
public void setStats(){
|
|
ItemStack weapon = npc.inventory.getWeapon();
|
|
npc.stats.setAttackStrength((float) (1 + getSwordDamage(weapon)));
|
|
npc.stats.healthRegen = 0;
|
|
npc.stats.combatRegen = 0;
|
|
int ranged = getTalentLevel(EnumCompanionTalent.RANGED);
|
|
if(ranged > 0 && weapon != null){
|
|
if(ranged > 0 && weapon.getItem() == Item.getItemFromBlock(Blocks.cobblestone)){
|
|
npc.inventory.setProjectile(weapon);
|
|
}
|
|
if(ranged > 0 && weapon.getItem() instanceof ItemBow){
|
|
npc.inventory.setProjectile(new ItemStack(Items.arrow));
|
|
}
|
|
}
|
|
|
|
inventory.setSize(2 + getTalentLevel(EnumCompanionTalent.INVENTORY) * 2);
|
|
}
|
|
|
|
public void setSelfsuficient(boolean bo){
|
|
if(owner == null || jobInterface != null && bo == jobInterface.isSelfSufficient())
|
|
return;
|
|
PlayerData data = PlayerDataController.instance.getPlayerData(owner);
|
|
if(!bo && data.hasCompanion())
|
|
return;
|
|
data.setCompanion(bo?null:npc);
|
|
if(job == EnumCompanionJobs.GUARD)
|
|
((CompanionGuard)jobInterface).isStanding = bo;
|
|
else if(job == EnumCompanionJobs.FARMER)
|
|
((CompanionFarmer)jobInterface).isStanding = bo;
|
|
|
|
}
|
|
|
|
public void setSitting(boolean sit){
|
|
if(sit){
|
|
npc.ai.animationType = EnumAnimation.SITTING;
|
|
npc.ai.onAttack = 3;
|
|
npc.ai.startPos = new int[]{MathHelper.floor_double(npc.posX),
|
|
MathHelper.floor_double(npc.posY), MathHelper.floor_double(npc.posZ)};
|
|
npc.getNavigator().clearPathEntity();
|
|
npc.setPositionAndUpdate(npc.ai.startPos[0] + 0.5, npc.posY, npc.ai.startPos[2] + 0.5);
|
|
}
|
|
else{
|
|
npc.ai.animationType = stage.animation;
|
|
npc.ai.onAttack = 0;
|
|
}
|
|
npc.setResponse();
|
|
}
|
|
|
|
public boolean isSitting(){
|
|
return npc.ai.animationType == EnumAnimation.SITTING;
|
|
}
|
|
|
|
public float applyArmorCalculations(DamageSource source, float damage) {
|
|
if(!hasInv || getTalentLevel(EnumCompanionTalent.ARMOR) <=0)
|
|
return damage;
|
|
if (!source.isUnblockable()){
|
|
damageArmor(damage);
|
|
int i = 25 - getTotalArmorValue();
|
|
float f1 = damage * (float)i;
|
|
damage = f1 / 25.0F;
|
|
}
|
|
return damage;
|
|
}
|
|
|
|
private void damageArmor(float damage){
|
|
damage /= 4.0F;
|
|
|
|
if (damage < 1.0F){
|
|
damage = 1.0F;
|
|
}
|
|
boolean hasArmor = false;
|
|
Iterator<Entry<Integer,ItemStack>> ita = npc.inventory.armor.entrySet().iterator();
|
|
while(ita.hasNext()){
|
|
Entry<Integer,ItemStack> entry = ita.next();
|
|
ItemStack item = entry.getValue();
|
|
if(item == null || !(item.getItem() instanceof ItemArmor))
|
|
continue;
|
|
hasArmor = true;
|
|
item.damageItem((int)damage, npc);
|
|
if(item.stackSize <= 0)
|
|
ita.remove();
|
|
}
|
|
this.gainExp(hasArmor?4:8);
|
|
}
|
|
|
|
public int getTotalArmorValue(){
|
|
int armorValue = 0;
|
|
for(ItemStack armor : npc.inventory.getArmor().values()){
|
|
if(armor != null && armor.getItem() instanceof ItemArmor)
|
|
armorValue += ((ItemArmor)armor.getItem()).damageReduceAmount;
|
|
}
|
|
return armorValue;
|
|
}
|
|
|
|
public boolean isFollowing(){
|
|
if(jobInterface != null && jobInterface.isSelfSufficient())
|
|
return false;
|
|
return owner != null && !isSitting();
|
|
}
|
|
|
|
@Override
|
|
public boolean defendOwner() {
|
|
if(!defendOwner || owner == null || stage == EnumCompanionStage.BABY || jobInterface != null && jobInterface.isSelfSufficient())
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
public int followRange() {
|
|
return 9 + 12 * stage.ordinal();
|
|
|
|
}
|
|
|
|
public boolean hasOwner() {
|
|
return !uuid.isEmpty();
|
|
}
|
|
|
|
public void addMovementStat(double x, double y, double z) {
|
|
int i = Math.round(MathHelper.sqrt_double(x * x + y * y + z * z) * 100.0F);
|
|
if(npc.isAttacking())
|
|
foodstats.addExhaustion(0.04F * (float)i * 0.01F);
|
|
else
|
|
foodstats.addExhaustion(0.02F * (float)i * 0.01F);
|
|
}
|
|
|
|
private ItemStack getFood(){
|
|
List<ItemStack> food = new ArrayList<ItemStack>(inventory.items.values());
|
|
Iterator<ItemStack> ite = food.iterator();
|
|
int i = -1;
|
|
while(ite.hasNext()){
|
|
ItemStack is = ite.next();
|
|
if(is == null || !(is.getItem() instanceof ItemFood)){
|
|
ite.remove();
|
|
continue;
|
|
}
|
|
int amount = ((ItemFood) is.getItem()).func_150905_g(is);
|
|
if(i == -1 || amount < i)
|
|
i = amount;
|
|
}
|
|
for(ItemStack is : food){
|
|
if(((ItemFood)is.getItem()).func_150905_g(is) == i)
|
|
return is;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public ItemStack getHeldItem() {
|
|
if(eating != null)
|
|
return eating;
|
|
return npc.inventory.getWeapon();
|
|
}
|
|
|
|
public boolean isEating() {
|
|
return eating != null;
|
|
}
|
|
|
|
public boolean hasInv() {
|
|
if(!hasInv)
|
|
return false;
|
|
return hasTalent(EnumCompanionTalent.INVENTORY) || hasTalent(EnumCompanionTalent.ARMOR) || hasTalent(EnumCompanionTalent.SWORD);
|
|
}
|
|
|
|
public void attackedEntity(Entity entity) {
|
|
ItemStack weapon = npc.inventory.getWeapon();
|
|
gainExp(weapon == null?8:4);
|
|
if(weapon == null)
|
|
return;
|
|
weapon.damageItem(1, npc);
|
|
if(weapon.stackSize <= 0)
|
|
npc.inventory.setWeapon(null);
|
|
}
|
|
|
|
public void addTalentExp(EnumCompanionTalent talent, int exp) {
|
|
if(talents.containsKey(talent))
|
|
exp += talents.get(talent);
|
|
talents.put(talent, exp);
|
|
}
|
|
}
|