prevRotationPitch = axes.getPitch();
prevRotationRoll = axes.getRoll();
if(angularVelocity.lengthSquared() > 0.00000001F)
axes.rotateLocal(angularVelocity.length(), angularVelocity.normalise(null));
Vector3f posVec = new Vector3f(posX, posY, posZ);
Vector3f motVec = new Vector3f(motionX, motionY, motionZ);
Vector3f nextPosVec = Vector3f.add(posVec, motVec, null);
//Raytrace the motion of this grenade
MovingObjectPosition hit = worldObj.rayTraceBlocks(posVec.toVec3(), nextPosVec.toVec3());
//If we hit block
if(hit != null && hit.typeOfHit == MovingObjectType.BLOCK)
{
//Get the blockID and block material
Block block = worldObj.getBlock(hit.blockX, hit.blockY, hit.blockZ);
Material mat = block.getMaterial();
//If this grenade detonates on impact, do so
if(type.explodeOnImpact)
detonate();
//If we hit glass and can break it, do so
else if(type.breaksGlass && mat == Material.glass && TeamsManager.canBreakGlass)
{
worldObj.setBlockToAir(hit.blockX, hit.blockY, hit.blockZ);
FlansMod.proxy.playBlockBreakSound(hit.blockX, hit.blockY, hit.blockZ, block);
}
//If this grenade does not penetrate blocks, hit the block instead
//The grenade cannot bounce if it detonated on impact, so hence the "else" condition
else if(!type.penetratesBlocks)
{
Vector3f hitVec = new Vector3f(hit.hitVec);
//Motion of the grenade pre-hit
Vector3f preHitMotVec = Vector3f.sub(hitVec, posVec, null);
//Motion of the grenade post-hit
Vector3f postHitMotVec = Vector3f.sub(motVec, preHitMotVec, null);
//Reflect postHitMotVec based on side hit
int sideHit = hit.sideHit;
switch(sideHit)
{
case 0 : case 1 : postHitMotVec.setY(-postHitMotVec.getY()); break;
case 4 : case 5 : postHitMotVec.setX(-postHitMotVec.getX()); break;
case 2 : case 3 : postHitMotVec.setZ(-postHitMotVec.getZ()); break;
}
//Calculate the time interval spent post reflection
float lambda = Math.abs(motVec.lengthSquared()) < 0.00000001F ? 1F : postHitMotVec.length() / motVec.length();
//Scale the post hit motion by the bounciness of the grenade
postHitMotVec.scale(type.bounciness / 2);
//Move the grenade along the new path including reflection
posX += preHitMotVec.x + postHitMotVec.x;
posY += preHitMotVec.y + postHitMotVec.y;
posZ += preHitMotVec.z + postHitMotVec.z;
//Set the motion
motionX = postHitMotVec.x / lambda;
motionY = postHitMotVec.y / lambda;
motionZ = postHitMotVec.z / lambda;
//Reset the motion vector
motVec = new Vector3f(motionX, motionY, motionZ);
//Give it a random spin
float randomSpinner = 90F;
Vector3f.add(angularVelocity, new Vector3f(rand.nextGaussian() * randomSpinner, rand.nextGaussian() * randomSpinner, rand.nextGaussian() * randomSpinner), angularVelocity);
//Slow the spin based on the motion
angularVelocity.scale(motVec.lengthSquared());
//Play the bounce sound
if(motVec.lengthSquared() > 0.01D)
playSound(type.bounceSound, 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F));
//If this grenade is sticky, stick it to the block
if(type.sticky)
{
//Move the grenade to the point of contact
posX = hitVec.x;
posY = hitVec.y;
posZ = hitVec.z;
//Stop all motion of the grenade
motionX = motionY = motionZ = 0;
angularVelocity.set(0F, 0F, 0F);
float yaw = axes.getYaw();
switch(hit.sideHit)
{
case 0 : axes.setAngles(yaw, 180F, 0F); break;
case 1 : axes.setAngles(yaw, 0F, 0F); break;
case 2 : axes.setAngles(270F, 90F, 0F); axes.rotateLocalYaw(yaw); break;
case 3 : axes.setAngles(90F, 90F, 0F); axes.rotateLocalYaw(yaw); break;
case 4 : axes.setAngles(180F, 90F, 0F); axes.rotateLocalYaw(yaw); break;
case 5 : axes.setAngles(0F, 90F, 0F); axes.rotateLocalYaw(yaw); break;
}
//Set the stuck flag on
stuck = true;
stuckToX = hit.blockX;
stuckToY = hit.blockY;
stuckToZ = hit.blockZ;
}
}
}
//We didn't hit a block, continue as normal
else
{
posX += motionX;
posY += motionY;
posZ += motionZ;
}
//Update the grenade position
setPosition(posX, posY, posZ);
}
if(type.stickToThrower)
{
if(thrower == null || thrower.isDead)
setDead();
else setPosition(thrower.posX, thrower.posY, thrower.posZ);
}
//If throwing this grenade at an entity should hurt them, this bit checks for entities in the way and does so
//(Don't attack entities when stuck to stuff)
if(type.damageVsLiving > 0 && !stuck)
{
Vector3f motVec = new Vector3f(motionX, motionY, motionZ);
List list = worldObj.getEntitiesWithinAABBExcludingEntity(this, boundingBox);
for(Object obj : list)
{
if(obj == thrower && ticksExisted < 10 || motVec.lengthSquared() < 0.01D)
continue;
if(obj instanceof EntityLivingBase)
((EntityLivingBase)obj).attackEntityFrom(getGrenadeDamage(), type.damageVsLiving * motVec.lengthSquared() * 3);
}
}
//Apply gravity
motionY -= 9.81D / 400D * type.fallSpeed;