return;
//Create a list for all bullet hits
ArrayList<BulletHit> hits = new ArrayList<BulletHit>();
Vector3f origin = new Vector3f(posX, posY, posZ);
Vector3f motion = new Vector3f(motionX, motionY, motionZ);
float speed = motion.length();
//Iterate over all entities
for(int i = 0; i < worldObj.loadedEntityList.size(); i++)
{
Object obj = worldObj.loadedEntityList.get(i);
//Get driveables
if(obj instanceof EntityDriveable)
{
EntityDriveable driveable = (EntityDriveable)obj;
if(driveable.isDead() || driveable.isPartOfThis(owner))
continue;
//If this bullet is within the driveable's detection range
if(getDistanceToEntity(driveable) <= driveable.getDriveableType().bulletDetectionRadius + speed)
{
//Raytrace the bullet
ArrayList<BulletHit> driveableHits = driveable.attackFromBullet(origin, motion);
hits.addAll(driveableHits);
}
}
//Get players
else if(obj instanceof EntityPlayer)
{
EntityPlayer player = (EntityPlayer)obj;
PlayerData data = PlayerHandler.getPlayerData(player);
boolean shouldDoNormalHitDetect = false;
if(data != null)
{
if(player.isDead || data.team == Team.spectators)
{
continue;
}
if(player == owner && ticksInAir < 20)
continue;
int snapshotToTry = pingOfShooter / 50;
if(snapshotToTry >= data.snapshots.length)
snapshotToTry = data.snapshots.length - 1;
PlayerSnapshot snapshot = data.snapshots[snapshotToTry];
if(snapshot == null)
snapshot = data.snapshots[0];
//DEBUG
//snapshot = new PlayerSnapshot(player);
//Check one last time for a null snapshot. If this is the case, fall back to normal hit detection
if(snapshot == null)
shouldDoNormalHitDetect = true;
else
{
//Raytrace
ArrayList<BulletHit> playerHits = snapshot.raytrace(origin, motion);
hits.addAll(playerHits);
}
}
//If we couldn't get a snapshot, use normal entity hitbox calculations
if(data == null || shouldDoNormalHitDetect)
{
MovingObjectPosition mop = player.boundingBox.calculateIntercept(origin.toVec3(), Vec3.createVectorHelper(posX + motionX, posY + motionY, posZ + motionZ));
if(mop != null)
{
Vector3f hitPoint = new Vector3f(mop.hitVec.xCoord - posX, mop.hitVec.yCoord - posY, mop.hitVec.zCoord - posZ);
float hitLambda = 1F;
if(motion.x != 0F)
hitLambda = hitPoint.x / motion.x;
else if(motion.y != 0F)
hitLambda = hitPoint.y / motion.y;
else if(motion.z != 0F)
hitLambda = hitPoint.z / motion.z;
if(hitLambda < 0)
hitLambda = -hitLambda;
hits.add(new PlayerBulletHit(new PlayerHitbox(player, new RotatedAxes(), new Vector3f(), new Vector3f(), new Vector3f(), EnumHitboxType.BODY), hitLambda));
}
}
}
else
{
Entity entity = (Entity)obj;
if(entity != this && entity != owner && !entity.isDead && (entity instanceof EntityLivingBase || entity instanceof EntityAAGun || entity instanceof EntityGrenade))
{
MovingObjectPosition mop = entity.boundingBox.calculateIntercept(origin.toVec3(), Vec3.createVectorHelper(posX + motionX, posY + motionY, posZ + motionZ));
if(mop != null)
{
Vector3f hitPoint = new Vector3f(mop.hitVec.xCoord - posX, mop.hitVec.yCoord - posY, mop.hitVec.zCoord - posZ);
float hitLambda = 1F;
if(motion.x != 0F)
hitLambda = hitPoint.x / motion.x;
else if(motion.y != 0F)
hitLambda = hitPoint.y / motion.y;
else if(motion.z != 0F)
hitLambda = hitPoint.z / motion.z;
if(hitLambda < 0)
hitLambda = -hitLambda;
hits.add(new EntityHit(entity, hitLambda));
}
}
}
}
//Ray trace the bullet by comparing its next position to its current position
Vec3 posVec = Vec3.createVectorHelper(posX, posY, posZ);
Vec3 nextPosVec = Vec3.createVectorHelper(posX + motionX, posY + motionY, posZ + motionZ);
MovingObjectPosition hit = worldObj.func_147447_a(posVec, nextPosVec, false, true, true);
posVec = Vec3.createVectorHelper(posX, posY, posZ);
if(hit != null)
{
//Calculate the lambda value of the intercept
Vec3 hitVec = posVec.subtract(hit.hitVec);
float lambda = 1;
//Try each co-ordinate one at a time.
if(motionX != 0)
lambda = (float)(hitVec.xCoord / motionX);
else if(motionY != 0)
lambda = (float)(hitVec.yCoord / motionY);
else if(motionZ != 0)
lambda = (float)(hitVec.zCoord / motionZ);
if(lambda < 0)
lambda = -lambda;
hits.add(new BlockHit(hit, lambda));
}
//We hit something
if(!hits.isEmpty())
{
//Sort the hits according to the intercept position
Collections.sort(hits);
for(BulletHit bulletHit : hits)
{
if(bulletHit instanceof DriveableHit)
{
DriveableHit driveableHit = (DriveableHit)bulletHit;
penetratingPower = driveableHit.driveable.bulletHit(this, driveableHit, penetratingPower);
if(FlansMod.DEBUG)
worldObj.spawnEntityInWorld(new EntityDebugDot(worldObj, new Vector3f(posX + motionX * driveableHit.intersectTime, posY + motionY * driveableHit.intersectTime, posZ + motionZ * driveableHit.intersectTime), 1000, 0F, 0F, 1F));
}
else if(bulletHit instanceof PlayerBulletHit)
{
PlayerBulletHit playerHit = (PlayerBulletHit)bulletHit;
penetratingPower = playerHit.hitbox.hitByBullet(this, penetratingPower);
if(FlansMod.DEBUG)
worldObj.spawnEntityInWorld(new EntityDebugDot(worldObj, new Vector3f(posX + motionX * playerHit.intersectTime, posY + motionY * playerHit.intersectTime, posZ + motionZ * playerHit.intersectTime), 1000, 1F, 0F, 0F));
}
else if(bulletHit instanceof EntityHit)
{
EntityHit entityHit = (EntityHit)bulletHit;
if(entityHit.entity.attackEntityFrom(getBulletDamage(false), damage * type.damageVsLiving) && entityHit.entity instanceof EntityLivingBase)
{
EntityLivingBase living = (EntityLivingBase)entityHit.entity;
for(PotionEffect effect : type.hitEffects)
{
living.addPotionEffect(new PotionEffect(effect));
}
//If the attack was allowed, we should remove their immortality cooldown so we can shoot them again. Without this, any rapid fire gun become useless
living.arrowHitTimer++;
living.hurtResistantTime = living.maxHurtResistantTime / 2;
}
if(type.setEntitiesOnFire)
entityHit.entity.setFire(20);
penetratingPower -= 1F;
if(FlansMod.DEBUG)
worldObj.spawnEntityInWorld(new EntityDebugDot(worldObj, new Vector3f(posX + motionX * entityHit.intersectTime, posY + motionY * entityHit.intersectTime, posZ + motionZ * entityHit.intersectTime), 1000, 1F, 1F, 0F));
}
else if(bulletHit instanceof BlockHit)
{
BlockHit blockHit = (BlockHit)bulletHit;
MovingObjectPosition raytraceResult = blockHit.raytraceResult;
//If the hit wasn't an entity hit, then it must've been a block hit
int xTile = raytraceResult.blockX;
int yTile = raytraceResult.blockY;
int zTile = raytraceResult.blockZ;
if(FlansMod.DEBUG)
worldObj.spawnEntityInWorld(new EntityDebugDot(worldObj, new Vector3f(raytraceResult.hitVec.xCoord, raytraceResult.hitVec.yCoord, raytraceResult.hitVec.zCoord), 1000, 0F, 1F, 0F));
Block block = worldObj.getBlock(xTile, yTile, zTile);
Material mat = block.getMaterial();
//If the bullet breaks glass, and can do so according to FlansMod, do so.
if(type.breaksGlass && mat == Material.glass)
{
if(TeamsManager.canBreakGlass)
{
worldObj.setBlockToAir(xTile, yTile, zTile);
FlansMod.proxy.playBlockBreakSound(xTile, yTile, zTile, block);
}
}
//penetratingPower -= block.getBlockHardness(worldObj, zTile, zTile, zTile);
setPosition(hit.hitVec.xCoord, hit.hitVec.yCoord, hit.hitVec.zCoord);
setDead();
break;
}
if(penetratingPower <= 0F || (type.explodeOnImpact && ticksInAir > 1))
{
setPosition(posX + motionX * bulletHit.intersectTime, posY + motionY * bulletHit.intersectTime, posZ + motionZ * bulletHit.intersectTime);
setDead();
break;
}
}
}
//Otherwise, do a standard check for uninteresting entities
/*
else
{
//Iterate over entities close to the bullet to see if any of them have been hit and hit them
List list = worldObj.getEntitiesWithinAABBExcludingEntity(this, boundingBox.addCoord(motionX, motionY, motionZ).expand(type.hitBoxSize, type.hitBoxSize, type.hitBoxSize));
for (int l = 0; l < list.size(); l++)
{
Entity checkEntity = (Entity) list.get(l);
//Driveable collisions are handled earlier
if(checkEntity instanceof EntityDriveable)
continue;
if(checkEntity instanceof EntityPlayer)
continue;
//Stop the bullet hitting stuff that can't be collided with or the person shooting immediately after firing it
if((!checkEntity.canBeCollidedWith() || isPartOfOwner(checkEntity)) && ticksInAir < 20)
{
continue;
}
//Calculate the hit damage
float hitDamage = damage * type.damageVsLiving;
//Create a damage source object
DamageSource damagesource = owner == null ? DamageSource.generic : getBulletDamage(false);
//When the damage is 0 (such as with Nerf guns) the entityHurt Forge hook is not called, so this hacky thing is here
if(hitDamage == 0 && checkEntity instanceof EntityPlayerMP && TeamsManager.getInstance().currentRound != null)
TeamsManager.getInstance().currentRound.gametype.playerAttacked((EntityPlayerMP)checkEntity, damagesource);
//Attack the entity!
if(checkEntity.attackEntityFrom(damagesource, hitDamage))
{
//If the attack was allowed and the entity is alive, we should remove their immortality cooldown so we can shoot them again. Without this, any rapid fire gun become useless
if (checkEntity instanceof EntityLivingBase)
{
((EntityLivingBase) checkEntity).arrowHitTimer++;
((EntityLivingBase) checkEntity).hurtResistantTime = ((EntityLivingBase) checkEntity).maxHurtResistantTime / 2;
}
//Yuck.
//PacketDispatcher.sendPacketToAllAround(posX, posY, posZ, 50, dimension, PacketPlaySound.buildSoundPacket(posX, posY, posZ, type.hitSound, true));
}
//Unless the bullet penetrates, kill it
if(type.penetratingPower > 0)
{
setPosition(checkEntity.posX, checkEntity.posY, checkEntity.posZ);
setDead();
break;
}
}
}
*/
//Movement dampening variables
float drag = 0.99F;
float gravity = 0.02F;
//If the bullet is in water, spawn particles and increase the drag
if (isInWater())
{
for(int i = 0; i < 4; i++)
{
float bubbleMotion = 0.25F;
worldObj.spawnParticle("bubble", posX - motionX * bubbleMotion, posY - motionY * bubbleMotion, posZ - motionZ * bubbleMotion, motionX, motionY, motionZ);
}
drag = 0.8F;
}
motionX *= drag;
motionY *= drag;
motionZ *= drag;
motionY -= gravity * type.fallSpeed;
//Apply homing action
if(lockedOnTo != null)
{
double dX = lockedOnTo.posX - posX;
double dY = lockedOnTo.posY - posY;
double dZ = lockedOnTo.posZ - posZ;
double dXYZ = Math.sqrt(dX * dX + dY * dY + dZ * dZ);
Vector3f relPosVec = new Vector3f(lockedOnTo.posX - posX, lockedOnTo.posY - posY, lockedOnTo.posZ - posZ);
float angle = Math.abs(Vector3f.angle(motion, relPosVec));
double lockOnPull = angle / 2F * type.lockOnForce;
motionX += lockOnPull * dX / dXYZ;