Jump to content

[1.8]Help with entity that swims like the Guardian


NovaViper

Recommended Posts

I'm trying to create an entity that moves around on land like a normal entity, but also when it enters water, it swims smoothly in the water like the Guardian and have it attack entities on land and water. How am I to achieve this?

Main Developer and Owner of Zero Quest

Visit the Wiki for more information

If I helped anyone, please give me a applaud and a thank you!

Link to comment
Share on other sites

Well.. at first, I entirely copied the Guardian's code into the model, then I completely cleared it out since I was still working on the model for the entity at the time, so this is what I have so far

 

package common.zeroquest.entity;

import net.minecraft.entity.EntityAgeable;
import net.minecraft.entity.passive.EntityAnimal;
import net.minecraft.pathfinding.PathNavigateGround;
import net.minecraft.world.World;

import com.google.common.base.Predicate;

public class EntityRowarn extends EntityAnimal {

public EntityRowarn(World worldIn) {
	super(worldIn);
	this.setSize(0.6F, 2.6F);
	this.stepHeight = 1;
	((PathNavigateGround) this.getNavigator()).func_179688_b(true);
}

@Override
public EntityAgeable createChild(EntityAgeable ageable) {
	// TODO Auto-generated method stub
	return null;
}
}

Main Developer and Owner of Zero Quest

Visit the Wiki for more information

If I helped anyone, please give me a applaud and a thank you!

Link to comment
Share on other sites

Ok, I started coping code from the Guardian and resulted with this

 

package common.zeroquest.entity;

import java.util.Iterator;
import java.util.List;

import net.minecraft.block.material.Material;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityAgeable;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.EntityAIBase;
import net.minecraft.entity.ai.EntityAILookIdle;
import net.minecraft.entity.ai.EntityAIMoveTowardsRestriction;
import net.minecraft.entity.ai.EntityAINearestAttackableTarget;
import net.minecraft.entity.ai.EntityAIWander;
import net.minecraft.entity.ai.EntityAIWatchClosest;
import net.minecraft.entity.ai.EntityLookHelper;
import net.minecraft.entity.ai.EntityMoveHelper;
import net.minecraft.entity.passive.EntityAnimal;
import net.minecraft.entity.passive.EntitySquid;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.entity.projectile.EntityFishHook;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.item.ItemFishFood;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.play.server.S2BPacketChangeGameState;
import net.minecraft.pathfinding.PathNavigate;
import net.minecraft.pathfinding.PathNavigateSwimmer;
import net.minecraft.potion.Potion;
import net.minecraft.potion.PotionEffect;
import net.minecraft.util.BlockPos;
import net.minecraft.util.DamageSource;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.util.MathHelper;
import net.minecraft.util.Vec3;
import net.minecraft.util.WeightedRandom;
import net.minecraft.util.WeightedRandomFishable;
import net.minecraft.world.EnumDifficulty;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;

import com.google.common.base.Predicate;

public class EntityRowarn extends EntityAnimal {
private float field_175482_b;
private float field_175484_c;
private float field_175483_bk;
private float field_175485_bl;
private float field_175486_bm;
private EntityLivingBase field_175478_bn;
private int field_175479_bo;
private boolean field_175480_bp;
private EntityAIWander wander;
private static final String __OBFID = "CL_00002213";

public EntityRowarn(World worldIn) {
	super(worldIn);
	this.experienceValue = 10;
	this.setSize(0.85F, 0.85F);
	this.tasks.addTask(4, new EntityRowarn.AIGuardianAttack());
	EntityAIMoveTowardsRestriction entityaimovetowardsrestriction;
	this.tasks.addTask(5, entityaimovetowardsrestriction = new EntityAIMoveTowardsRestriction(this, 1.0D));
	this.tasks.addTask(7, this.wander = new EntityAIWander(this, 1.0D, 80));
	this.tasks.addTask(8, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F));
	this.tasks.addTask(8, new EntityAIWatchClosest(this, EntityRowarn.class, 12.0F, 0.01F));
	this.tasks.addTask(9, new EntityAILookIdle(this));
	this.wander.setMutexBits(3);
	entityaimovetowardsrestriction.setMutexBits(3);
	this.moveHelper = new EntityRowarn.GuardianMoveHelper();
	this.field_175484_c = this.field_175482_b = this.rand.nextFloat();
}

@Override
protected void applyEntityAttributes() {
	super.applyEntityAttributes();
	this.getEntityAttribute(SharedMonsterAttributes.movementSpeed).setBaseValue(0.5D);
	this.getEntityAttribute(SharedMonsterAttributes.followRange).setBaseValue(16.0D);
	this.getEntityAttribute(SharedMonsterAttributes.maxHealth).setBaseValue(30.0D);
}

/**
 * (abstract) Protected helper method to read subclass entity data from NBT.
 */
@Override
public void readEntityFromNBT(NBTTagCompound tagCompund) {
	super.readEntityFromNBT(tagCompund);
}

/**
 * (abstract) Protected helper method to write subclass entity data to NBT.
 */
@Override
public void writeEntityToNBT(NBTTagCompound tagCompound) {
	super.writeEntityToNBT(tagCompound);
}

@Override
protected PathNavigate func_175447_b(World worldIn) {
	return new PathNavigateSwimmer(this, worldIn);
}

@Override
protected void entityInit() {
	super.entityInit();
	this.dataWatcher.addObject(16, Integer.valueOf(0));
	this.dataWatcher.addObject(17, Integer.valueOf(0));
}

private boolean func_175468_a(int p_175468_1_) {
	return (this.dataWatcher.getWatchableObjectInt(16) & p_175468_1_) != 0;
}

private void func_175473_a(int p_175473_1_, boolean p_175473_2_) {
	int j = this.dataWatcher.getWatchableObjectInt(16);

	if (p_175473_2_) {
		this.dataWatcher.updateObject(16, Integer.valueOf(j | p_175473_1_));
	}
	else {
		this.dataWatcher.updateObject(16, Integer.valueOf(j & ~p_175473_1_));
	}
}

public boolean func_175472_n() {
	return this.func_175468_a(2);
}

private void func_175476_l(boolean p_175476_1_) {
	this.func_175473_a(2, p_175476_1_);
}

@SideOnly(Side.CLIENT)
public void func_175465_cm() {
	this.field_175486_bm = this.field_175485_bl = 1.0F;
}

private void func_175463_b(int p_175463_1_) {
	this.dataWatcher.updateObject(17, Integer.valueOf(p_175463_1_));
}

public boolean func_175474_cn() {
	return this.dataWatcher.getWatchableObjectInt(17) != 0;
}

public EntityLivingBase getTargetedEntity() {
	if (!this.func_175474_cn()) {
		return null;
	}
	else if (this.worldObj.isRemote) {
		if (this.field_175478_bn != null) {
			return this.field_175478_bn;
		}
		else {
			Entity entity = this.worldObj.getEntityByID(this.dataWatcher.getWatchableObjectInt(17));

			if (entity instanceof EntityLivingBase) {
				this.field_175478_bn = (EntityLivingBase) entity;
				return this.field_175478_bn;
			}
			else {
				return null;
			}
		}
	}
	else {
		return this.getAttackTarget();
	}
}

@Override
public void func_145781_i(int p_145781_1_) {
	super.func_145781_i(p_145781_1_);

	if (p_145781_1_ == 16) {
		this.field_175479_bo = 0;
		this.field_175478_bn = null;
	}
}

/**
 * Get number of ticks, at least during which the living entity will be
 * silent.
 */
@Override
public int getTalkInterval() {
	return 160;
}

/**
 * Returns the sound this mob makes while it's alive.
 */
@Override
protected String getLivingSound() {
	return !this.isInWater() ? "mob.guardian.land.idle" : "mob.guardian.idle";
}

/**
 * Returns the sound this mob makes when it is hurt.
 */
@Override
protected String getHurtSound() {
	return !this.isInWater() ? "mob.guardian.land.hit" : "mob.guardian.hit";
}

/**
 * Returns the sound this mob makes on death.
 */
@Override
protected String getDeathSound() {
	return !this.isInWater() ? "mob.guardian.land.death" : "mob.guardian.death";
}

/**
 * returns if this entity triggers Block.onEntityWalking on the blocks they
 * walk on. used for spiders and wolves to prevent them from trampling crops
 */
@Override
protected boolean canTriggerWalking() {
	return false;
}

@Override
public float getEyeHeight() {
	return this.height * 0.5F;
}

@Override
public float func_180484_a(BlockPos p_180484_1_) {
	return this.worldObj.getBlockState(p_180484_1_).getBlock().getMaterial() == Material.water
			? 10.0F + this.worldObj.getLightBrightness(p_180484_1_) - 0.5F
			: super.func_180484_a(p_180484_1_);
}

/**
 * Called frequently so the entity can update its state every tick as
 * required. For example, zombies and skeletons use this to react to
 * sunlight and start to burn.
 */
@Override
public void onLivingUpdate() {
	if (this.worldObj.isRemote) {
		this.field_175484_c = this.field_175482_b;

		if (!this.isInWater()) {
			this.field_175483_bk = 2.0F;

			if (this.motionY > 0.0D && this.field_175480_bp && !this.isSilent()) {
				this.worldObj.playSound(this.posX, this.posY, this.posZ, "mob.guardian.flop", 1.0F, 1.0F, false);
			}

			this.field_175480_bp = this.motionY < 0.0D && this.worldObj.isBlockNormalCube((new BlockPos(this)).down(), false);
		}
		else if (this.func_175472_n()) {
			if (this.field_175483_bk < 0.5F) {
				this.field_175483_bk = 4.0F;
			}
			else {
				this.field_175483_bk += (0.5F - this.field_175483_bk) * 0.1F;
			}
		}
		else {
			this.field_175483_bk += (0.125F - this.field_175483_bk) * 0.2F;
		}

		this.field_175482_b += this.field_175483_bk;
		this.field_175486_bm = this.field_175485_bl;

		if (!this.isInWater()) {
			this.field_175485_bl = this.rand.nextFloat();
		}
		else if (this.func_175472_n()) {
			this.field_175485_bl += (0.0F - this.field_175485_bl) * 0.25F;
		}
		else {
			this.field_175485_bl += (1.0F - this.field_175485_bl) * 0.06F;
		}

		if (this.func_175472_n() && this.isInWater()) {
			Vec3 vec3 = this.getLook(0.0F);

			for (int i = 0; i < 2; ++i) {
				this.worldObj.spawnParticle(EnumParticleTypes.WATER_BUBBLE, this.posX + (this.rand.nextDouble() - 0.5D) * this.width - vec3.xCoord * 1.5D, this.posY + this.rand.nextDouble() * this.height - vec3.yCoord * 1.5D, this.posZ + (this.rand.nextDouble() - 0.5D) * this.width - vec3.zCoord * 1.5D, 0.0D, 0.0D, 0.0D, new int[0]);
			}
		}

		if (this.func_175474_cn()) {

			EntityLivingBase entitylivingbase = this.getTargetedEntity();

			if (entitylivingbase != null) {
				this.getLookHelper().setLookPositionWithEntity(entitylivingbase, 90.0F, 90.0F);
				this.getLookHelper().onUpdateLook();
				double d5 = 0.0F;
				double d0 = entitylivingbase.posX - this.posX;
				double d1 = entitylivingbase.posY + entitylivingbase.height * 0.5F - (this.posY + this.getEyeHeight());
				double d2 = entitylivingbase.posZ - this.posZ;
				double d3 = Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2);
				d0 /= d3;
				d1 /= d3;
				d2 /= d3;
				double d4 = this.rand.nextDouble();

				while (d4 < d3) {
					d4 += 1.8D - d5 + this.rand.nextDouble() * (1.7D - d5);
					this.worldObj.spawnParticle(EnumParticleTypes.WATER_BUBBLE, this.posX + d0 * d4, this.posY + d1 * d4 + this.getEyeHeight(), this.posZ + d2 * d4, 0.0D, 0.0D, 0.0D, new int[0]);
				}
			}
		}
	}

	if (this.inWater) {
		this.setAir(300);
	}
	else if (this.onGround) {
		this.motionY += 0.5D;
		this.motionX += (this.rand.nextFloat() * 2.0F - 1.0F) * 0.4F;
		this.motionZ += (this.rand.nextFloat() * 2.0F - 1.0F) * 0.4F;
		this.rotationYaw = this.rand.nextFloat() * 360.0F;
		this.onGround = false;
		this.isAirBorne = true;
	}

	if (this.func_175474_cn()) {
		this.rotationYaw = this.rotationYawHead;
	}

	super.onLivingUpdate();
}

@SideOnly(Side.CLIENT)
public float func_175471_a(float p_175471_1_) {
	return this.field_175484_c + (this.field_175482_b - this.field_175484_c) * p_175471_1_;
}

@SideOnly(Side.CLIENT)
public float func_175469_o(float p_175469_1_) {
	return this.field_175486_bm + (this.field_175485_bl - this.field_175486_bm) * p_175469_1_;
}

@Override
protected void updateAITasks() {
	super.updateAITasks();

	if (!this.hasHome()) {
		this.func_175449_a(new BlockPos(this), 16);
	}
}

/**
 * Drop 0-2 items of this living's type
 */
@Override
protected void dropFewItems(boolean p_70628_1_, int p_70628_2_) {
	int j = this.rand.nextInt(3) + this.rand.nextInt(p_70628_2_ + 1);

	if (j > 0) {
		this.entityDropItem(new ItemStack(Items.prismarine_shard, j, 0), 1.0F);
	}

	if (this.rand.nextInt(3 + p_70628_2_) > 1) {
		this.entityDropItem(new ItemStack(Items.fish, 1, ItemFishFood.FishType.COD.getMetadata()), 1.0F);
	}
	else if (this.rand.nextInt(3 + p_70628_2_) > 1) {
		this.entityDropItem(new ItemStack(Items.prismarine_crystals, 1, 0), 1.0F);
	}
}

/**
 * Makes entity wear random armor based on difficulty
 */
@Override
protected void addRandomArmor() {
	ItemStack itemstack = ((WeightedRandomFishable) WeightedRandom.getRandomItem(this.rand, EntityFishHook.func_174855_j())).getItemStack(this.rand);
	this.entityDropItem(itemstack, 1.0F);
}

/**
 * Checks to make sure the light is not too bright where the mob is spawning
 */
protected boolean isValidLightLevel() {
	return true;
}

/**
 * Whether or not the current entity is in lava
 */
@Override
public boolean handleLavaMovement() {
	return this.worldObj.checkNoEntityCollision(this.getEntityBoundingBox(), this) && this.worldObj.getCollidingBoundingBoxes(this, this.getEntityBoundingBox()).isEmpty();
}

/**
 * Checks if the entity's current position is a valid location to spawn this
 * entity.
 */
@Override
public boolean getCanSpawnHere() {
	return (this.rand.nextInt(20) == 0 || !this.worldObj.canBlockSeeSky(new BlockPos(this))) && super.getCanSpawnHere();
}

/**
 * Called when the entity is attacked.
 */
@Override
public boolean attackEntityFrom(DamageSource source, float amount) {
	if (!this.func_175472_n() && !source.isMagicDamage() && source.getSourceOfDamage() instanceof EntityLivingBase) {
		EntityLivingBase entitylivingbase = (EntityLivingBase) source.getSourceOfDamage();

		if (!source.isExplosion()) {
			entitylivingbase.attackEntityFrom(DamageSource.causeThornsDamage(this), 2.0F);
			entitylivingbase.playSound("damage.thorns", 0.5F, 1.0F);
		}
	}

	this.wander.func_179480_f();
	return super.attackEntityFrom(source, amount);
}

/**
 * The speed it takes to move the entityliving's rotationPitch through the
 * faceEntity method. This is only currently use in wolves.
 */
@Override
public int getVerticalFaceSpeed() {
	return 180;
}

/**
 * Moves the entity based on the specified heading. Args: strafe, forward
 */
@Override
public void moveEntityWithHeading(float p_70612_1_, float p_70612_2_) {
	if (this.isServerWorld()) {
		if (this.isInWater()) {
			this.moveFlying(p_70612_1_, p_70612_2_, 0.1F);
			this.moveEntity(this.motionX, this.motionY, this.motionZ);
			this.motionX *= 0.8999999761581421D;
			this.motionY *= 0.8999999761581421D;
			this.motionZ *= 0.8999999761581421D;

			if (!this.func_175472_n() && this.getAttackTarget() == null) {
				this.motionY -= 0.005D;
			}
		}
		else {
			super.moveEntityWithHeading(p_70612_1_, p_70612_2_);
		}
	}
	else {
		super.moveEntityWithHeading(p_70612_1_, p_70612_2_);
	}
}

class AIGuardianAttack extends EntityAIBase {
	private final EntityRowarn field_179456_a = EntityRowarn.this;
	private int field_179455_b;
	private static final String __OBFID = "CL_00002211";

	public AIGuardianAttack() {
		this.setMutexBits(3);
	}

	/**
	 * Returns whether the EntityAIBase should begin execution.
	 */
	@Override
	public boolean shouldExecute() {
		EntityLivingBase entitylivingbase = this.field_179456_a.getAttackTarget();
		return entitylivingbase != null && entitylivingbase.isEntityAlive();
	}

	/**
	 * Returns whether an in-progress EntityAIBase should continue executing
	 */
	@Override
	public boolean continueExecuting() {
		return super.continueExecuting() && this.field_179456_a.getDistanceSqToEntity(this.field_179456_a.getAttackTarget()) > 9.0D;
	}

	/**
	 * Execute a one shot task or start executing a continuous task
	 */
	@Override
	public void startExecuting() {
		this.field_179455_b = -10;
		this.field_179456_a.getNavigator().clearPathEntity();
		this.field_179456_a.getLookHelper().setLookPositionWithEntity(this.field_179456_a.getAttackTarget(), 90.0F, 90.0F);
		this.field_179456_a.isAirBorne = true;
	}

	/**
	 * Resets the task
	 */
	@Override
	public void resetTask() {
		this.field_179456_a.func_175463_b(0);
		this.field_179456_a.setAttackTarget((EntityLivingBase) null);
		this.field_179456_a.wander.func_179480_f();
	}

	/**
	 * Updates the task
	 */
	@Override
	public void updateTask() {
		EntityLivingBase entitylivingbase = this.field_179456_a.getAttackTarget();
		this.field_179456_a.getNavigator().clearPathEntity();
		this.field_179456_a.getLookHelper().setLookPositionWithEntity(entitylivingbase, 90.0F, 90.0F);

		if (!this.field_179456_a.canEntityBeSeen(entitylivingbase)) {
			this.field_179456_a.setAttackTarget((EntityLivingBase) null);
		}
		else {
			++this.field_179455_b;

			if (this.field_179455_b == 0) {
				this.field_179456_a.func_175463_b(this.field_179456_a.getAttackTarget().getEntityId());
				this.field_179456_a.worldObj.setEntityState(this.field_179456_a, (byte) 21);
			}
			else if (this.field_179455_b >= 60 && this.field_179455_b % 20 == 0) {
				;
			}

			super.updateTask();
		}
	}
}

class GuardianMoveHelper extends EntityMoveHelper {
	private final EntityRowarn field_179930_g = EntityRowarn.this;
	private static final String __OBFID = "CL_00002209";

	public GuardianMoveHelper() {
		super(EntityRowarn.this);
	}

	@Override
	public void onUpdateMoveHelper() {
		if (this.update && !this.field_179930_g.getNavigator().noPath()) {
			double d0 = this.posX - this.field_179930_g.posX;
			double d1 = this.posY - this.field_179930_g.posY;
			double d2 = this.posZ - this.field_179930_g.posZ;
			double d3 = d0 * d0 + d1 * d1 + d2 * d2;
			d3 = MathHelper.sqrt_double(d3);
			d1 /= d3;
			float f = (float) (Math.atan2(d2, d0) * 180.0D / Math.PI) - 90.0F;
			this.field_179930_g.rotationYaw = this.limitAngle(this.field_179930_g.rotationYaw, f, 30.0F);
			this.field_179930_g.renderYawOffset = this.field_179930_g.rotationYaw;
			float f1 = (float) (this.speed * this.field_179930_g.getEntityAttribute(SharedMonsterAttributes.movementSpeed).getAttributeValue());
			this.field_179930_g.setAIMoveSpeed(this.field_179930_g.getAIMoveSpeed() + (f1 - this.field_179930_g.getAIMoveSpeed()) * 0.125F);
			double d4 = Math.sin((this.field_179930_g.ticksExisted + this.field_179930_g.getEntityId()) * 0.5D) * 0.05D;
			double d5 = Math.cos(this.field_179930_g.rotationYaw * (float) Math.PI / 180.0F);
			double d6 = Math.sin(this.field_179930_g.rotationYaw * (float) Math.PI / 180.0F);
			this.field_179930_g.motionX += d4 * d5;
			this.field_179930_g.motionZ += d4 * d6;
			d4 = Math.sin((this.field_179930_g.ticksExisted + this.field_179930_g.getEntityId()) * 0.75D) * 0.05D;
			this.field_179930_g.motionY += d4 * (d6 + d5) * 0.25D;
			this.field_179930_g.motionY += this.field_179930_g.getAIMoveSpeed() * d1 * 0.1D;
			EntityLookHelper entitylookhelper = this.field_179930_g.getLookHelper();
			double d7 = this.field_179930_g.posX + d0 / d3 * 2.0D;
			double d8 = this.field_179930_g.getEyeHeight() + this.field_179930_g.posY + d1 / d3 * 1.0D;
			double d9 = this.field_179930_g.posZ + d2 / d3 * 2.0D;
			double d10 = entitylookhelper.func_180423_e();
			double d11 = entitylookhelper.func_180422_f();
			double d12 = entitylookhelper.func_180421_g();

			if (!entitylookhelper.func_180424_b()) {
				d10 = d7;
				d11 = d8;
				d12 = d9;
			}

			this.field_179930_g.getLookHelper().setLookPosition(d10 + (d7 - d10) * 0.125D, d11 + (d8 - d11) * 0.125D, d12 + (d9 - d12) * 0.125D, 10.0F, 40.0F);
			this.field_179930_g.func_175476_l(true);
		}
		else {
			this.field_179930_g.setAIMoveSpeed(0.0F);
			this.field_179930_g.func_175476_l(false);
		}
	}
}

@Override
public EntityAgeable createChild(EntityAgeable ageable) {
	// TODO Auto-generated method stub
	return null;
}
}

Main Developer and Owner of Zero Quest

Visit the Wiki for more information

If I helped anyone, please give me a applaud and a thank you!

Link to comment
Share on other sites

By the way, many of those methods with difficult names like func_175447_b() actually now have human-readable names -- in this case getNavigator().

 

To update the SRG mappings, in your build.gradle file add a mappings reference. For example, in my current 1.8 mods my build.gradle includes the following:

    minecraft {

        version = "1.8-11.14.1.1410"

        runDir = "../run/assets"

        mappings = "snapshot_20150518"

    }

 

Then you need to run gradlew setupDecompWorkspace and gradlew eclipse again. Then your code will be easier to read.

 

Anyway, so you're making a good start. But I think the getNavigator() method should return different navigator depending on whether your entity is on land or water. Also, I'm not sure exactly how to get the land navigator to get into the water, so you may have to detect that you're close to the water then change navigator.

 

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Link to comment
Share on other sites

That helped me a good bit.. but I'm still trying to see what pieces of code I don't need, since the guardian has parameters for the elder, I want to remove those and only leave the nagavitor switching codes

 

package common.zeroquest.entity;

import com.google.common.base.Predicate;

import java.util.Iterator;
import java.util.List;

import net.minecraft.block.material.Material;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityAgeable;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.EntityAIBase;
import net.minecraft.entity.ai.EntityAILookIdle;
import net.minecraft.entity.ai.EntityAIMoveTowardsRestriction;
import net.minecraft.entity.ai.EntityAINearestAttackableTarget;
import net.minecraft.entity.ai.EntityAIWander;
import net.minecraft.entity.ai.EntityAIWatchClosest;
import net.minecraft.entity.ai.EntityLookHelper;
import net.minecraft.entity.ai.EntityMoveHelper;
import net.minecraft.entity.passive.EntityAnimal;
import net.minecraft.entity.passive.EntitySquid;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.entity.projectile.EntityFishHook;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.item.ItemFishFood;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.play.server.S2BPacketChangeGameState;
import net.minecraft.pathfinding.PathNavigate;
import net.minecraft.pathfinding.PathNavigateSwimmer;
import net.minecraft.potion.Potion;
import net.minecraft.potion.PotionEffect;
import net.minecraft.util.BlockPos;
import net.minecraft.util.DamageSource;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.util.MathHelper;
import net.minecraft.util.Vec3;
import net.minecraft.util.WeightedRandom;
import net.minecraft.util.WeightedRandomFishable;
import net.minecraft.world.EnumDifficulty;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;

public class EntityRowarn extends EntityAnimal
{
    private float field_175482_b;
    private float field_175484_c;
    private float field_175483_bk;
    private float field_175485_bl;
    private float field_175486_bm;
    private EntityLivingBase targetedEntity;
    private int field_175479_bo;
    private boolean field_175480_bp;
    private EntityAIWander wander;
    private static final String __OBFID = "CL_00002213";

    public EntityRowarn(World worldIn)
    {
        super(worldIn);
        this.experienceValue = 10;
        this.setSize(0.85F, 0.85F);
        EntityAIMoveTowardsRestriction entityaimovetowardsrestriction;
        this.tasks.addTask(5, entityaimovetowardsrestriction = new EntityAIMoveTowardsRestriction(this, 1.0D));
        this.tasks.addTask(7, this.wander = new EntityAIWander(this, 1.0D, 80));
        this.tasks.addTask(8, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F));
        this.tasks.addTask(8, new EntityAIWatchClosest(this, EntityRowarn.class, 12.0F, 0.01F));
        this.tasks.addTask(9, new EntityAILookIdle(this));
        this.wander.setMutexBits(3);
        entityaimovetowardsrestriction.setMutexBits(3);
        this.moveHelper = new EntityRowarn.GuardianMoveHelper();
        this.field_175484_c = this.field_175482_b = this.rand.nextFloat();
    }

    protected void applyEntityAttributes()
    {
        super.applyEntityAttributes();
        this.getEntityAttribute(SharedMonsterAttributes.movementSpeed).setBaseValue(0.5D);
        this.getEntityAttribute(SharedMonsterAttributes.followRange).setBaseValue(16.0D);
        this.getEntityAttribute(SharedMonsterAttributes.maxHealth).setBaseValue(30.0D);
    }

    /**
     * (abstract) Protected helper method to read subclass entity data from NBT.
     */
    public void readEntityFromNBT(NBTTagCompound tagCompund)
    {
        super.readEntityFromNBT(tagCompund);
    }

    /**
     * (abstract) Protected helper method to write subclass entity data to NBT.
     */
    public void writeEntityToNBT(NBTTagCompound tagCompound)
    {
        super.writeEntityToNBT(tagCompound);
    }

    /**
     * Returns new PathNavigateGround instance
     */
    protected PathNavigate getNewNavigator(World worldIn)
    {
        return new PathNavigateSwimmer(this, worldIn);
    }

    protected void entityInit()
    {
        super.entityInit();
        this.dataWatcher.addObject(16, Integer.valueOf(0));
    }

    /**
     * Returns true if given flag is set
     */
    private boolean isSyncedFlagSet(int flagId)
    {
        return (this.dataWatcher.getWatchableObjectInt(16) & flagId) != 0;
    }

    /**
     * Sets a flag state "on/off" on both sides (client/server) by using DataWatcher
     *  
     * @param flagId flag byte
     */
    private void setSyncedFlag(int flagId, boolean state)
    {
        int j = this.dataWatcher.getWatchableObjectInt(16);

        if (state)
        {
            this.dataWatcher.updateObject(16, Integer.valueOf(j | flagId));
        }
        else
        {
            this.dataWatcher.updateObject(16, Integer.valueOf(j & ~flagId));
        }
    }

    public boolean func_175472_n()
    {
        return this.isSyncedFlagSet(2);
    }

    private void func_175476_l(boolean p_175476_1_)
    {
        this.setSyncedFlag(2, p_175476_1_);
    }

    private void func_175463_b(int p_175463_1_)
    {
        this.dataWatcher.updateObject(17, Integer.valueOf(p_175463_1_));
    }

    public boolean hasTargetedEntity()
    {
        return this.dataWatcher.getWatchableObjectInt(17) != 0;
    }

    public EntityLivingBase getTargetedEntity()
    {
        if (!this.hasTargetedEntity())
        {
            return null;
        }
        else if (this.worldObj.isRemote)
        {
            if (this.targetedEntity != null)
            {
                return this.targetedEntity;
            }
            else
            {
                Entity entity = this.worldObj.getEntityByID(this.dataWatcher.getWatchableObjectInt(17));

                if (entity instanceof EntityLivingBase)
                {
                    this.targetedEntity = (EntityLivingBase)entity;
                    return this.targetedEntity;
                }
                else
                {
                    return null;
                }
            }
        }
        else
        {
            return this.getAttackTarget();
        }
    }

    public void func_145781_i(int p_145781_1_)
    {
        super.func_145781_i(p_145781_1_);

        if (p_145781_1_ == 16)
        {
            this.field_175479_bo = 0;
            this.targetedEntity = null;
        }
    }

    /**
     * Get number of ticks, at least during which the living entity will be silent.
     */
    public int getTalkInterval()
    {
        return 160;
    }

    /**
     * Returns the sound this mob makes while it's alive.
     */
    protected String getLivingSound()
    {
        return !this.isInWater() ? "mob.guardian.land.idle" : "mob.guardian.idle";
    }

    /**
     * Returns the sound this mob makes when it is hurt.
     */
    protected String getHurtSound()
    {
        return !this.isInWater() ? "mob.guardian.land.hit" : "mob.guardian.hit";
    }

    /**
     * Returns the sound this mob makes on death.
     */
    protected String getDeathSound()
    {
        return !this.isInWater() ? "mob.guardian.land.death" :"mob.guardian.death";
    }

    /**
     * returns if this entity triggers Block.onEntityWalking on the blocks they walk on. used for spiders and wolves to
     * prevent them from trampling crops
     */
    protected boolean canTriggerWalking()
    {
        return false;
    }

    public float getEyeHeight()
    {
        return this.height * 0.5F;
    }

    public float getBlockPathWeight(BlockPos pos)
    {
        return this.worldObj.getBlockState(pos).getBlock().getMaterial() == Material.water ? 10.0F + this.worldObj.getLightBrightness(pos) - 0.5F : super.getBlockPathWeight(pos);
    }

    /**
     * Called frequently so the entity can update its state every tick as required. For example, zombies and skeletons
     * use this to react to sunlight and start to burn.
     */
    public void onLivingUpdate()
    {
        if (this.worldObj.isRemote)
        {
            this.field_175484_c = this.field_175482_b;

            if (!this.isInWater())
            {
                this.field_175483_bk = 2.0F;

                if (this.motionY > 0.0D && this.field_175480_bp && !this.isSilent())
                {
                    this.worldObj.playSound(this.posX, this.posY, this.posZ, "mob.guardian.flop", 1.0F, 1.0F, false);
                }

                this.field_175480_bp = this.motionY < 0.0D && this.worldObj.isBlockNormalCube((new BlockPos(this)).down(), false);
            }
            else if (this.func_175472_n())
            {
                if (this.field_175483_bk < 0.5F)
                {
                    this.field_175483_bk = 4.0F;
                }
                else
                {
                    this.field_175483_bk += (0.5F - this.field_175483_bk) * 0.1F;
                }
            }
            else
            {
                this.field_175483_bk += (0.125F - this.field_175483_bk) * 0.2F;
            }

            this.field_175482_b += this.field_175483_bk;
            this.field_175486_bm = this.field_175485_bl;

            if (!this.isInWater())
            {
                this.field_175485_bl = this.rand.nextFloat();
            }
            else if (this.func_175472_n())
            {
                this.field_175485_bl += (0.0F - this.field_175485_bl) * 0.25F;
            }
            else
            {
                this.field_175485_bl += (1.0F - this.field_175485_bl) * 0.06F;
            }

            if (this.func_175472_n() && this.isInWater())
            {
                Vec3 vec3 = this.getLook(0.0F);

                for (int i = 0; i < 2; ++i)
                {
                    this.worldObj.spawnParticle(EnumParticleTypes.WATER_BUBBLE, this.posX + (this.rand.nextDouble() - 0.5D) * (double)this.width - vec3.xCoord * 1.5D, this.posY + this.rand.nextDouble() * (double)this.height - vec3.yCoord * 1.5D, this.posZ + (this.rand.nextDouble() - 0.5D) * (double)this.width - vec3.zCoord * 1.5D, 0.0D, 0.0D, 0.0D, new int[0]);
                }
            }

            if (this.hasTargetedEntity())
            {

                EntityLivingBase entitylivingbase = this.getTargetedEntity();

                if (entitylivingbase != null)
                {
                    this.getLookHelper().setLookPositionWithEntity(entitylivingbase, 90.0F, 90.0F);
                    this.getLookHelper().onUpdateLook();
                    double d5 = (double)this.func_175477_p(0.0F);
                    double d0 = entitylivingbase.posX - this.posX;
                    double d1 = entitylivingbase.posY + (double)(entitylivingbase.height * 0.5F) - (this.posY + (double)this.getEyeHeight());
                    double d2 = entitylivingbase.posZ - this.posZ;
                    double d3 = Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2);
                    d0 /= d3;
                    d1 /= d3;
                    d2 /= d3;
                    double d4 = this.rand.nextDouble();

                    while (d4 < d3)
                    {
                        d4 += 1.8D - d5 + this.rand.nextDouble() * (1.7D - d5);
                        this.worldObj.spawnParticle(EnumParticleTypes.WATER_BUBBLE, this.posX + d0 * d4, this.posY + d1 * d4 + (double)this.getEyeHeight(), this.posZ + d2 * d4, 0.0D, 0.0D, 0.0D, new int[0]);
                    }
                }
            }
        }

        if (this.inWater)
        {
            this.setAir(300);
        }
        else if (this.onGround)
        {
        	this.wander.startExecuting();
        }

        if (this.hasTargetedEntity())
        {
            this.rotationYaw = this.rotationYawHead;
        }

        super.onLivingUpdate();
    }

    @SideOnly(Side.CLIENT)
    public float func_175471_a(float p_175471_1_)
    {
        return this.field_175484_c + (this.field_175482_b - this.field_175484_c) * p_175471_1_;
    }

    @SideOnly(Side.CLIENT)
    public float func_175469_o(float p_175469_1_)
    {
        return this.field_175486_bm + (this.field_175485_bl - this.field_175486_bm) * p_175469_1_;
    }

    public float func_175477_p(float p_175477_1_)
    {
        return ((float)this.field_175479_bo + p_175477_1_);
    }

    protected void updateAITasks()
    {
        super.updateAITasks();

            if (!this.hasHome())
            {
                this.setHomePosAndDistance(new BlockPos(this), 16);
            }
    }

    /**
     * Drop 0-2 items of this living's type
     */
    protected void dropFewItems(boolean p_70628_1_, int p_70628_2_)
    {
        int j = this.rand.nextInt(3) + this.rand.nextInt(p_70628_2_ + 1);

        if (j > 0)
        {
            this.entityDropItem(new ItemStack(Items.prismarine_shard, j, 0), 1.0F);
        }

        if (this.rand.nextInt(3 + p_70628_2_) > 1)
        {
            this.entityDropItem(new ItemStack(Items.fish, 1, ItemFishFood.FishType.COD.getMetadata()), 1.0F);
        }
        else if (this.rand.nextInt(3 + p_70628_2_) > 1)
        {
            this.entityDropItem(new ItemStack(Items.prismarine_crystals, 1, 0), 1.0F);
        }
    }

    /**
     * Whether or not the current entity is in lava
     */
    public boolean handleLavaMovement()
    {
        return this.worldObj.checkNoEntityCollision(this.getEntityBoundingBox(), this) && this.worldObj.getCollidingBoundingBoxes(this, this.getEntityBoundingBox()).isEmpty();
    }

    /**
     * The speed it takes to move the entityliving's rotationPitch through the faceEntity method. This is only currently
     * use in wolves.
     */
    public int getVerticalFaceSpeed()
    {
        return 180;
    }

    /**
     * Moves the entity based on the specified heading.  Args: strafe, forward
     */
    public void moveEntityWithHeading(float strafe, float forward)
    {
        if (this.isServerWorld())
        {
            if (this.isInWater())
            {
                this.moveFlying(strafe, forward, 0.1F);
                this.moveEntity(this.motionX, this.motionY, this.motionZ);
                this.motionX *= 0.8999999761581421D;
                this.motionY *= 0.8999999761581421D;
                this.motionZ *= 0.8999999761581421D;

                if (!this.func_175472_n() && this.getAttackTarget() == null)
                {
                    this.motionY -= 0.005D;
                }
            }
            else
            {
                super.moveEntityWithHeading(strafe, forward);
            }
        }
        else
        {
            super.moveEntityWithHeading(strafe, forward);
        }
    }

    class GuardianMoveHelper extends EntityMoveHelper
    {
        private EntityRowarn entityGuardian = EntityRowarn.this;
        private static final String __OBFID = "CL_00002209";

        public GuardianMoveHelper()
        {
            super(EntityRowarn.this);
        }

        public void onUpdateMoveHelper()
        {
            if (this.update && !this.entityGuardian.getNavigator().noPath())
            {
                double d0 = this.posX - this.entityGuardian.posX;
                double d1 = this.posY - this.entityGuardian.posY;
                double d2 = this.posZ - this.entityGuardian.posZ;
                double d3 = d0 * d0 + d1 * d1 + d2 * d2;
                d3 = (double)MathHelper.sqrt_double(d3);
                d1 /= d3;
                float f = (float)(Math.atan2(d2, d0) * 180.0D / Math.PI) - 90.0F;
                this.entityGuardian.rotationYaw = this.limitAngle(this.entityGuardian.rotationYaw, f, 30.0F);
                this.entityGuardian.renderYawOffset = this.entityGuardian.rotationYaw;
                float f1 = (float)(this.speed * this.entityGuardian.getEntityAttribute(SharedMonsterAttributes.movementSpeed).getAttributeValue());
                this.entityGuardian.setAIMoveSpeed(this.entityGuardian.getAIMoveSpeed() + (f1 - this.entityGuardian.getAIMoveSpeed()) * 0.125F);
                double d4 = Math.sin((double)(this.entityGuardian.ticksExisted + this.entityGuardian.getEntityId()) * 0.5D) * 0.05D;
                double d5 = Math.cos((double)(this.entityGuardian.rotationYaw * (float)Math.PI / 180.0F));
                double d6 = Math.sin((double)(this.entityGuardian.rotationYaw * (float)Math.PI / 180.0F));
                this.entityGuardian.motionX += d4 * d5;
                this.entityGuardian.motionZ += d4 * d6;
                d4 = Math.sin((double)(this.entityGuardian.ticksExisted + this.entityGuardian.getEntityId()) * 0.75D) * 0.05D;
                this.entityGuardian.motionY += d4 * (d6 + d5) * 0.25D;
                this.entityGuardian.motionY += (double)this.entityGuardian.getAIMoveSpeed() * d1 * 0.1D;
                EntityLookHelper entitylookhelper = this.entityGuardian.getLookHelper();
                double d7 = this.entityGuardian.posX + d0 / d3 * 2.0D;
                double d8 = (double)this.entityGuardian.getEyeHeight() + this.entityGuardian.posY + d1 / d3 * 1.0D;
                double d9 = this.entityGuardian.posZ + d2 / d3 * 2.0D;
                double d10 = entitylookhelper.getLookPosX();
                double d11 = entitylookhelper.getLookPosY();
                double d12 = entitylookhelper.getLookPosZ();

                if (!entitylookhelper.getIsLooking())
                {
                    d10 = d7;
                    d11 = d8;
                    d12 = d9;
                }

                this.entityGuardian.getLookHelper().setLookPosition(d10 + (d7 - d10) * 0.125D, d11 + (d8 - d11) * 0.125D, d12 + (d9 - d12) * 0.125D, 10.0F, 40.0F);
                this.entityGuardian.func_175476_l(true);
            }
            else
            {
                this.entityGuardian.setAIMoveSpeed(0.0F);
                this.entityGuardian.func_175476_l(false);
            }
        }
    }

@Override
public EntityAgeable createChild(EntityAgeable ageable) {
	// TODO Auto-generated method stub
	return null;
}
}

Main Developer and Owner of Zero Quest

Visit the Wiki for more information

If I helped anyone, please give me a applaud and a thank you!

Link to comment
Share on other sites

Also I've been getting this crash log whenver minecraft loads up

 

[23:26:04] [main/INFO] [GradleStart]: Extra: []
[23:26:05] [main/INFO] [GradleStart]: Running with arguments: [--userProperties, {}, --assetsDir, C:/Users/NovaPC/.gradle/caches/minecraft/assets, --assetIndex, 1.8, --accessToken, {REDACTED}, --version, 1.8, --tweakClass, net.minecraftforge.fml.common.launcher.FMLTweaker, --tweakClass, net.minecraftforge.gradle.tweakers.CoremodTweaker]
[23:26:05] [main/INFO] [LaunchWrapper]: Loading tweak class name net.minecraftforge.fml.common.launcher.FMLTweaker
[23:26:05] [main/INFO] [LaunchWrapper]: Using primary tweak class name net.minecraftforge.fml.common.launcher.FMLTweaker
[23:26:05] [main/INFO] [LaunchWrapper]: Loading tweak class name net.minecraftforge.gradle.tweakers.CoremodTweaker
[23:26:05] [main/INFO] [LaunchWrapper]: Calling tweak class net.minecraftforge.fml.common.launcher.FMLTweaker
[23:26:05] [main/INFO] [FML]: Forge Mod Loader version 8.99.14.1416 for Minecraft 1.8 loading
[23:26:05] [main/INFO] [FML]: Java is Java HotSpot(TM) 64-Bit Server VM, version 1.8.0_25, running on Windows 7:amd64:6.1, installed at C:\Program Files\Java\jre1.8.0_25
[23:26:05] [main/INFO] [FML]: Managed to load a deobfuscated Minecraft name- we are in a deobfuscated environment. Skipping runtime deobfuscation
[23:26:05] [main/INFO] [LaunchWrapper]: Calling tweak class net.minecraftforge.gradle.tweakers.CoremodTweaker
[23:26:05] [main/INFO] [GradleStart]: Injecting location in coremod net.minecraftforge.fml.relauncher.FMLCorePlugin
[23:26:05] [main/INFO] [GradleStart]: Injecting location in coremod net.minecraftforge.classloading.FMLForgePlugin
[23:26:05] [main/INFO] [LaunchWrapper]: Loading tweak class name net.minecraftforge.fml.common.launcher.FMLInjectionAndSortingTweaker
[23:26:05] [main/INFO] [LaunchWrapper]: Loading tweak class name net.minecraftforge.fml.common.launcher.FMLDeobfTweaker
[23:26:05] [main/INFO] [LaunchWrapper]: Loading tweak class name net.minecraftforge.gradle.tweakers.AccessTransformerTweaker
[23:26:05] [main/INFO] [LaunchWrapper]: Calling tweak class net.minecraftforge.fml.common.launcher.FMLInjectionAndSortingTweaker
[23:26:05] [main/INFO] [LaunchWrapper]: Calling tweak class net.minecraftforge.fml.common.launcher.FMLInjectionAndSortingTweaker
[23:26:05] [main/INFO] [LaunchWrapper]: Calling tweak class net.minecraftforge.fml.relauncher.CoreModManager$FMLPluginWrapper
[23:26:06] [main/ERROR] [FML]: The binary patch set is missing. Either you are in a development environment, or things are not going to work!
[23:26:10] [main/ERROR] [FML]: FML appears to be missing any signature data. This is not a good thing
[23:26:10] [main/INFO] [LaunchWrapper]: Calling tweak class net.minecraftforge.fml.relauncher.CoreModManager$FMLPluginWrapper
[23:26:10] [main/INFO] [LaunchWrapper]: Calling tweak class net.minecraftforge.fml.common.launcher.FMLDeobfTweaker
[23:26:11] [main/INFO] [LaunchWrapper]: Calling tweak class net.minecraftforge.gradle.tweakers.AccessTransformerTweaker
[23:26:11] [main/INFO] [LaunchWrapper]: Loading tweak class name net.minecraftforge.fml.common.launcher.TerminalTweaker
[23:26:11] [main/INFO] [LaunchWrapper]: Calling tweak class net.minecraftforge.fml.common.launcher.TerminalTweaker
[23:26:11] [main/INFO] [LaunchWrapper]: Launching wrapped minecraft {net.minecraft.client.main.Main}
[23:26:15] [Client thread/INFO]: Setting user: Player901
[23:26:22] [Client thread/INFO]: LWJGL Version: 2.9.1
[23:26:23] [Client thread/INFO] [FML]: Could not load splash.properties, will create a default one
[23:26:24] [Client thread/INFO] [sTDOUT]: [net.minecraftforge.fml.client.SplashProgress:start:233]: ---- Minecraft Crash Report ----
// Shall we play a game?

Time: 5/25/15 11:26 PM
Description: Loading screen debug info

This is just a prompt for computer specs to be printed. THIS IS NOT A ERROR


A detailed walkthrough of the error, its code path and all known details is as follows:
---------------------------------------------------------------------------------------

-- System Details --
Details:
Minecraft Version: 1.8
Operating System: Windows 7 (amd64) version 6.1
Java Version: 1.8.0_25, Oracle Corporation
Java VM Version: Java HotSpot(TM) 64-Bit Server VM (mixed mode), Oracle Corporation
Memory: 775727752 bytes (739 MB) / 1038876672 bytes (990 MB) up to 1038876672 bytes (990 MB)
JVM Flags: 3 total; -Xincgc -Xmx1024M -Xms1024M
IntCache: cache: 0, tcache: 0, allocated: 0, tallocated: 0
FML: 
Loaded coremods (and transformers): 
GL info: ' Vendor: 'ATI Technologies Inc.' Version: '4.1.11156 Compatibility Profile Context' Renderer: 'AMD Radeon(TM) HD 6620G'

 

But the game still comes up, should I be concerned about this?

Main Developer and Owner of Zero Quest

Visit the Wiki for more information

If I helped anyone, please give me a applaud and a thank you!

Link to comment
Share on other sites

"This is just a prompt for computer specs to be printed. THIS IS NOT A ERROR

A detailed walkthrough of the error, its code path and all known details is as follows:"

 

It literally contradicts itself. Plus, there is no stack trace, pretty weird... does this happen even without your new entity's code?

Link to comment
Share on other sites

Hey, how do I make the entity actually walk around first and only when it hits the water it swims like the Guardian?

 

That's the tricky part. Honestly, you shouldn't try creating a mod unless you already have an idea on how you will make it work...

 

Anyway, the first question is: when do you want it to enter the water?

 

The general idea would be that at the point it should go into water you'd have an AI task that would find the closest water and head to it. Then when you detect that the entity is actually in the water (I think there is a method like isInWater() or similar you can check) then you'd switch the navigator to swimming navigator.

 

When doing custom stuff it is best to look at how other vanilla mobs do similar things. For example I think a burning zombie will purposefully go into water. So check how the zombie AI does that, but change the condition (in your case  you don't have to be burning).

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Link to comment
Share on other sites

I want it to get into the water when it detects it's attacker in the water and get out of the water and stay near it during the day, then go into the water at night. I have been at the zombie's entity coding, specifically the ones that have it move through the villages

Main Developer and Owner of Zero Quest

Visit the Wiki for more information

If I helped anyone, please give me a applaud and a thank you!

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.