Fixed entity interactions with force fields
Added ability for entities to pass through force field Added attraction/repulsion visual effects Fixed entity interaction scaling Fixed client crash when connecting to a server next to a force field
This commit is contained in:
parent
e067a3d8f3
commit
f4644d45de
6 changed files with 222 additions and 116 deletions
|
@ -23,5 +23,6 @@ public interface IForceFieldUpgradeEffector {
|
|||
|
||||
// Entity impact of this upgrade
|
||||
// Return
|
||||
int onEntityEffect(final float scaledValue, World world, final int x, final int y, final int z, Entity entity);
|
||||
int onEntityEffect(final float scaledValue, World world, final int projectorX, final int projectorY, final int projectorZ,
|
||||
final int blockX, final int blockY, final int blockZ, Entity entity);
|
||||
}
|
||||
|
|
|
@ -231,10 +231,6 @@ public class BlockForceField extends BlockAbstractForceField implements IDamageR
|
|||
log_explosionX = explosionX;
|
||||
log_explosionY = explosionY;
|
||||
log_explosionZ = explosionZ;
|
||||
if (WarpDriveConfig.LOGGING_FORCEFIELD) {
|
||||
WarpDrive.logger.info("BlockForceField(" + tier + " at " + x + " " + y + " " + z + ")"
|
||||
+ ".getExplosionResistance" + ((entity != null) ? " from " + entity : " at " + explosionX + " " + explosionY + " " + explosionZ));
|
||||
}
|
||||
}
|
||||
|
||||
// find explosion strength, defaults to no effect
|
||||
|
@ -255,8 +251,8 @@ public class BlockForceField extends BlockAbstractForceField implements IDamageR
|
|||
case "class net.minecraft.entity.item.EntityTNTPrimed": strength = 5.0F; break;
|
||||
case "class net.minecraft.entity.monster.EntityCreeper": strength = 3.0F; break; // *2 for powered ones
|
||||
case "class appeng.entity.EntityTinyTNTPrimed": strength = 0.2F; break;
|
||||
case "class ic2.core.block.EntityItnt": strength = 5.5F; break;
|
||||
case "class ic2.core.block.EntityNuke": strength = 42.0F; break;
|
||||
case "class ic2.core.block.EntityItnt": strength = 5.5F; break;
|
||||
case "class ic2.core.block.EntityNuke": strength = 45.0F; break;
|
||||
case "class ic2.core.block.EntityDynamite": strength = 1.0F; break;
|
||||
case "class ic2.core.block.EntityStickyDynamite": strength = 1.0F; break;
|
||||
default:
|
||||
|
@ -270,14 +266,24 @@ public class BlockForceField extends BlockAbstractForceField implements IDamageR
|
|||
// apply damages to force field by consuming energy
|
||||
Explosion explosion = new Explosion(world, entity, explosionX, explosionY, explosionZ, 4.0F);
|
||||
Vector3 vDirection = new Vector3(x + 0.5D - explosionX, y + 0.5D - explosionY, z + 0.5D - explosionZ);
|
||||
float magnitude = Math.max(1.0F, (float)vDirection.getMagnitude());
|
||||
double magnitude = Math.max(1.0D, vDirection.getMagnitude());
|
||||
if (magnitude != 0) {// normalize
|
||||
vDirection.scale(1 / magnitude);
|
||||
}
|
||||
int damageLevel = Math.round(strength * 1000.0F / magnitude);
|
||||
int damageLeft = applyDamage(world, x, y, z, DamageSource.setExplosionSource(explosion), 0, vDirection, damageLevel);
|
||||
double damageLevel = strength / (magnitude * magnitude) * 1.0D;
|
||||
double damageLeft = 0;
|
||||
ForceFieldSetup forceFieldSetup = getForceFieldSetup(world, x, y, z);
|
||||
if (forceFieldSetup != null) {
|
||||
damageLeft = forceFieldSetup.applyDamage(world, DamageSource.setExplosionSource(explosion), (int)damageLevel);
|
||||
}
|
||||
|
||||
assert(damageLeft >= 0);
|
||||
return 1.0F * super.getExplosionResistance(entity, world, x, y, z, explosionX, explosionY, explosionZ);
|
||||
if (WarpDriveConfig.LOGGING_FORCEFIELD) {
|
||||
WarpDrive.logger.info( "BlockForceField(" + tier + " at " + x + " " + y + " " + z + ")"
|
||||
+ ".getExplosionResistance" + ((entity != null) ? " from " + entity : " at " + explosionX + " " + explosionY + " " + explosionZ)
|
||||
+ " damageLevel " + damageLevel + " damageLeft " + damageLeft);
|
||||
}
|
||||
return super.getExplosionResistance(entity, world, x, y, z, explosionX, explosionY, explosionZ);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -60,10 +60,12 @@ public class TileEntityForceFieldProjector extends TileEntityAbstractForceField
|
|||
private int setupTicks;
|
||||
private int updateTicks;
|
||||
private int soundTicks;
|
||||
private final HashSet<UUID> setInteractedEntities = new HashSet<>();
|
||||
protected boolean isPowered = true;
|
||||
private ForceFieldSetup cache_forceFieldSetup;
|
||||
private ForceFieldSetup legacy_forceFieldSetup;
|
||||
private boolean legacy_isOn = true; // we assume it's on so we don't consume startup energy on chunk loading
|
||||
private double consumptionLeftOver = 0.0D;
|
||||
|
||||
// carry over speed to next tick, useful for slow interactions
|
||||
private float carryScanSpeed;
|
||||
|
@ -106,7 +108,6 @@ public class TileEntityForceFieldProjector extends TileEntityAbstractForceField
|
|||
cooldownTicks = worldObj.rand.nextInt(PROJECTOR_COOLDOWN_TICKS);
|
||||
setupTicks = worldObj.rand.nextInt(PROJECTOR_SETUP_TICKS);
|
||||
updateTicks = worldObj.rand.nextInt(PROJECTOR_PROJECTION_UPDATE_TICKS);
|
||||
getForceFieldSetup();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -136,10 +137,9 @@ public class TileEntityForceFieldProjector extends TileEntityAbstractForceField
|
|||
ForceFieldSetup forceFieldSetup = getForceFieldSetup();
|
||||
int energyRequired;
|
||||
if (!legacy_isOn) {
|
||||
energyRequired = forceFieldSetup.startupEnergyCost;
|
||||
energyRequired += Math.round(forceFieldSetup.placeEnergyCost * forceFieldSetup.placeSpeed * PROJECTOR_PROJECTION_UPDATE_TICKS / 20.0F);
|
||||
energyRequired = (int)Math.round(forceFieldSetup.startupEnergyCost + forceFieldSetup.placeEnergyCost * forceFieldSetup.placeSpeed * PROJECTOR_PROJECTION_UPDATE_TICKS / 20.0F);
|
||||
} else {
|
||||
energyRequired = Math.round(forceFieldSetup.scanEnergyCost * forceFieldSetup.scanSpeed * PROJECTOR_PROJECTION_UPDATE_TICKS / 20.0F);
|
||||
energyRequired = (int)Math.round( forceFieldSetup.scanEnergyCost * forceFieldSetup.scanSpeed * PROJECTOR_PROJECTION_UPDATE_TICKS / 20.0F);
|
||||
}
|
||||
if (energyRequired > getMaxEnergyStored()) {
|
||||
WarpDrive.logger.error("Force field projector requires " + energyRequired + " to get started but can only store " + getMaxEnergyStored());
|
||||
|
@ -151,10 +151,19 @@ public class TileEntityForceFieldProjector extends TileEntityAbstractForceField
|
|||
if (isOn) {
|
||||
if (!legacy_isOn) {
|
||||
consumeEnergy(forceFieldSetup.startupEnergyCost, false);
|
||||
if (WarpDriveConfig.LOGGING_FORCEFIELD) {
|
||||
WarpDrive.logger.info(this + " starting up...");
|
||||
}
|
||||
legacy_isOn = true;
|
||||
}
|
||||
cooldownTicks = 0;
|
||||
|
||||
int countEntityInteractions = setInteractedEntities.size();
|
||||
if (countEntityInteractions > 0) {
|
||||
setInteractedEntities.clear();
|
||||
consumeEnergy(forceFieldSetup.getEntityEnergyCost(countEntityInteractions), false);
|
||||
}
|
||||
|
||||
updateTicks--;
|
||||
if (updateTicks <= 0) {
|
||||
updateTicks = PROJECTOR_PROJECTION_UPDATE_TICKS;
|
||||
|
@ -174,7 +183,12 @@ public class TileEntityForceFieldProjector extends TileEntityAbstractForceField
|
|||
}
|
||||
|
||||
} else {
|
||||
legacy_isOn = false;
|
||||
if (legacy_isOn) {
|
||||
if (WarpDriveConfig.LOGGING_FORCEFIELD) {
|
||||
WarpDrive.logger.info(this + " shutting down...");
|
||||
}
|
||||
legacy_isOn = false;
|
||||
}
|
||||
destroyForceField(false);
|
||||
if (cooldownTicks > 0) {
|
||||
cooldownTicks--;
|
||||
|
@ -266,6 +280,10 @@ public class TileEntityForceFieldProjector extends TileEntityAbstractForceField
|
|||
return calculated_interiorField.contains(vector);
|
||||
}
|
||||
|
||||
public boolean onEntityInteracted(final UUID uniqueID) {
|
||||
return setInteractedEntities.add(uniqueID);
|
||||
}
|
||||
|
||||
private void projectForceField() {
|
||||
assert(!worldObj.isRemote && isCalculated());
|
||||
|
||||
|
@ -892,11 +910,14 @@ public class TileEntityForceFieldProjector extends TileEntityAbstractForceField
|
|||
|
||||
// reset field in case of major changes
|
||||
if (legacy_forceFieldSetup != null) {
|
||||
int energyRequired = cache_forceFieldSetup.startupEnergyCost - legacy_forceFieldSetup.startupEnergyCost;
|
||||
int energyRequired = (int)Math.max(0, Math.round(cache_forceFieldSetup.startupEnergyCost - legacy_forceFieldSetup.startupEnergyCost));
|
||||
if ( legacy_forceFieldSetup.getCamouflageBlock() != cache_forceFieldSetup.getCamouflageBlock()
|
||||
|| legacy_forceFieldSetup.getCamouflageMetadata() != cache_forceFieldSetup.getCamouflageMetadata()
|
||||
|| legacy_forceFieldSetup.beamFrequency != cache_forceFieldSetup.beamFrequency
|
||||
|| !consumeEnergy(energyRequired, false)) {
|
||||
if (WarpDriveConfig.LOGGING_FORCEFIELD) {
|
||||
WarpDrive.logger.info(this + " rebooting with new rendering...");
|
||||
}
|
||||
destroyForceField(true);
|
||||
|
||||
} else if ( legacy_forceFieldSetup.isInverted != cache_forceFieldSetup.isInverted
|
||||
|
@ -905,6 +926,9 @@ public class TileEntityForceFieldProjector extends TileEntityAbstractForceField
|
|||
|| !legacy_forceFieldSetup.vMin.equals(cache_forceFieldSetup.vMin)
|
||||
|| !legacy_forceFieldSetup.vMax.equals(cache_forceFieldSetup.vMax)
|
||||
|| !legacy_forceFieldSetup.vTranslation.equals(cache_forceFieldSetup.vTranslation)) {
|
||||
if (WarpDriveConfig.LOGGING_FORCEFIELD) {
|
||||
WarpDrive.logger.info(this + " rebooting with new shape...");
|
||||
}
|
||||
destroyForceField(true);
|
||||
isDirty.set(true);
|
||||
}
|
||||
|
@ -923,6 +947,15 @@ public class TileEntityForceFieldProjector extends TileEntityAbstractForceField
|
|||
return true;
|
||||
}
|
||||
|
||||
public boolean consumeEnergy(final double amount_internal, boolean simulate) {
|
||||
int intAmount = (int)Math.floor(amount_internal + consumptionLeftOver);
|
||||
boolean bResult = super.consumeEnergy(intAmount, simulate);
|
||||
if (!simulate) {
|
||||
consumptionLeftOver = amount_internal + consumptionLeftOver - intAmount;
|
||||
}
|
||||
return bResult;
|
||||
}
|
||||
|
||||
// OpenComputer callback methods
|
||||
@Callback
|
||||
@cpw.mods.fml.common.Optional.Method(modid = "OpenComputers")
|
||||
|
|
|
@ -20,26 +20,26 @@ import java.util.HashMap;
|
|||
|
||||
public enum EnumForceFieldUpgrade implements IForceFieldUpgrade, IForceFieldUpgradeEffector {
|
||||
// Upgrade - Compatibility - ----- Value ----- -- Scan speed -- -- Place speed -- --------- Energy costs --------- comment
|
||||
// name projector relay incr. cap minimum maximum minimum maximum startup scan place entity
|
||||
NONE ("none" , 0, 0, 0.0F, 0.0F, 0.000F, 0.000F, 0.000F, 0.000F, 0.0F, 0.000F, 0.000F, 0.0F, ""),
|
||||
ATTRACTION ("attraction" , 0, 1, 1.0F, 4.0F, 0.000F, 0.000F, 0.000F, 0.000F, 50.0F, 0.150F, 0.000F, 200.0F, "value is acceleration"),
|
||||
BREAKING ("breaking" , 0, 1, 1.0F, 25.0F, 0.400F, 0.500F, 0.020F, 0.150F, 700.0F, 0.080F, 4.000F, 0.0F, "value is hardness level"),
|
||||
CAMOUFLAGE ("camouflage" , 0, 1, 1.0F, 3.0F, 0.600F, 0.850F, 0.700F, 0.950F, 1000.0F, 3.000F, 7.000F, 0.0F, "value is boolean"),
|
||||
COOLING ("cooling" , 3, 1, 30.0F, 300.0F, 0.000F, 0.000F, 0.900F, 0.900F, 150.0F, 0.060F, 1.500F, 1000.0F, "value is heat units"),
|
||||
FUSION ("fusion" , 1, 1, 1.0F, 1.0F, 0.000F, 0.000F, 0.000F, 0.000F, 1000.0F, 0.150F, 0.150F, 0.0F, "value is boolean"),
|
||||
HEATING ("heating" , 3, 1, 100.0F, 10000.0F, 0.000F, 0.000F, 0.900F, 0.900F, 150.0F, 0.300F, 3.000F, 500.0F, "value is heat units"),
|
||||
INVERSION ("inversion" , 1, 0, 1.0F, 1.0F, 1.250F, 1.250F, 0.000F, 0.000F, 1500.0F, 0.150F, 0.150F, 100.0F, "value is boolean"),
|
||||
ITEM_PORT ("itemPort" , 0, 1, 1.0F, 10.0F, 0.000F, 0.000F, 0.950F, 0.900F, 50.0F, 0.120F, 0.500F, 800.0F, "value is boolean"),
|
||||
PUMPING ("pumping" , 0, 1, 1000.0F, 50000.0F, 0.800F, 1.000F, 0.400F, 1.000F, 800.0F, 0.500F, 2.250F, 0.0F, "value is viscosity"),
|
||||
RANGE ("range" , 4, 1, 8.0F, 56.0F, 1.150F, 0.800F, 1.150F, 0.800F, 10.0F, 0.300F, 0.750F, 400.0F, "value is bonus blocks"),
|
||||
REPULSION ("repulsion" , 0, 1, 1.0F, 4.0F, 0.000F, 0.000F, 0.000F, 0.000F, 50.0F, 0.150F, 0.000F, 200.0F, "value is acceleration"),
|
||||
ROTATION ("rotation" , 1, 0, 1.0F, 1.0F, 0.000F, 0.000F, 0.000F, 0.000F, 100.0F, 0.000F, 0.000F, 0.0F, "value is boolean"),
|
||||
SHOCK ("shock" , 3, 1, 1.0F, 10.0F, 0.800F, 0.800F, 0.800F, 0.800F, 300.0F, 0.600F, 4.000F, 3000.0F, "value is damage points"),
|
||||
SILENCER ("silencer" , 1, 0, 1.0F, 1.0F, 0.000F, 0.000F, 0.000F, 0.000F, 0.0F, 0.120F, 0.620F, 0.0F, "value is boolean"),
|
||||
SPEED ("speed" , 4, 1, 1.0F, 20.0F, 1.250F, 6.000F, 1.200F, 5.000F, 200.0F, 0.400F, 1.700F, 500.0F, "value is not used (just a counter)"),
|
||||
STABILIZATION("stabilization", 0, 1, 1.0F, 6.0F, 0.450F, 0.550F, 0.050F, 0.150F, 400.0F, 1.520F, 4.300F, 0.0F, "value is boolean"),
|
||||
THICKNESS ("thickness" , 5, 1, 0.2F, 1.0F, 0.800F, 1.600F, 0.000F, 0.000F, 100.0F, 0.700F, 2.400F, 100.0F, "value is bonus ratio"),
|
||||
TRANSLATION ("translation" , 1, 0, 1.0F, 1.0F, 0.000F, 0.000F, 0.000F, 0.000F, 100.0F, 0.000F, 0.000F, 0.0F, "value is boolean"),
|
||||
// name projector relay incr. cap minimum maximum minimum maximum startup scan place entity
|
||||
NONE ("none" , 0, 0, 0.0F, 0.0F, 0.000F, 0.000F, 0.000F, 0.000F, 0.0F, 0.000F, 0.000F, 0.0F, ""),
|
||||
ATTRACTION ("attraction" , 0, 1, 1.0F, 4.0F, 0.000F, 0.000F, 0.000F, 0.000F, 50.0F, 0.150F, 0.000F, 8.0F, "value is acceleration"),
|
||||
BREAKING ("breaking" , 0, 1, 1.0F, 25.0F, 0.400F, 0.500F, 0.020F, 0.150F, 700.0F, 0.080F, 4.000F, 0.0F, "value is hardness level"),
|
||||
CAMOUFLAGE ("camouflage" , 0, 1, 1.0F, 3.0F, 0.600F, 0.850F, 0.700F, 0.950F, 1000.0F, 3.000F, 7.000F, 0.0F, "value is boolean"),
|
||||
COOLING ("cooling" , 3, 1, 30.0F, 300.0F, 0.000F, 0.000F, 0.900F, 0.900F, 150.0F, 0.060F, 1.500F, 40.0F, "value is heat units"),
|
||||
FUSION ("fusion" , 1, 1, 1.0F, 1.0F, 0.000F, 0.000F, 0.000F, 0.000F, 1000.0F, 0.040F, 0.150F, 0.0F, "value is boolean"),
|
||||
HEATING ("heating" , 3, 1, 100.0F, 10000.0F, 0.000F, 0.000F, 0.900F, 0.900F, 150.0F, 0.300F, 3.000F, 25.0F, "value is heat units"),
|
||||
INVERSION ("inversion" , 1, 0, 1.0F, 1.0F, 1.250F, 1.250F, 0.000F, 0.000F, 1500.0F, 0.150F, 0.150F, 20.0F, "value is boolean"),
|
||||
ITEM_PORT ("itemPort" , 0, 1, 1.0F, 10.0F, 0.000F, 0.000F, 0.950F, 0.900F, 50.0F, 0.120F, 0.500F, 2.0F, "value is boolean"),
|
||||
PUMPING ("pumping" , 0, 1, 1000.0F, 50000.0F, 0.800F, 1.000F, 0.400F, 1.000F, 800.0F, 0.150F, 4.500F, 0.0F, "value is viscosity"),
|
||||
RANGE ("range" , 4, 1, 8.0F, 56.0F, 1.150F, 0.800F, 1.150F, 0.800F, 10.0F, 0.300F, 0.750F, 12.0F, "value is bonus blocks"),
|
||||
REPULSION ("repulsion" , 0, 1, 1.0F, 4.0F, 0.000F, 0.000F, 0.000F, 0.000F, 50.0F, 0.150F, 0.000F, 5.0F, "value is acceleration"),
|
||||
ROTATION ("rotation" , 1, 0, 1.0F, 1.0F, 0.000F, 0.000F, 0.000F, 0.000F, 100.0F, 0.000F, 0.000F, 0.0F, "value is boolean"),
|
||||
SHOCK ("shock" , 3, 1, 1.0F, 10.0F, 0.800F, 0.800F, 0.800F, 0.800F, 300.0F, 0.600F, 4.000F, 30.0F, "value is damage points"),
|
||||
SILENCER ("silencer" , 1, 0, 1.0F, 1.0F, 0.000F, 0.000F, 0.000F, 0.000F, 0.0F, 0.120F, 0.620F, 0.0F, "value is boolean"),
|
||||
SPEED ("speed" , 4, 1, 1.0F, 20.0F, 1.250F, 6.000F, 1.200F, 5.000F, 200.0F, 0.135F, 1.250F, 15.0F, "value is not used (just a counter)"),
|
||||
STABILIZATION("stabilization", 0, 1, 1.0F, 6.0F, 0.250F, 0.550F, 0.025F, 0.150F, 400.0F, 0.050F, 73.600F, 0.0F, "value is boolean"),
|
||||
THICKNESS ("thickness" , 5, 1, 0.2F, 1.0F, 0.800F, 1.600F, 0.900F, 1.500F, 100.0F, 0.400F, 2.200F, 5.0F, "value is bonus ratio"),
|
||||
TRANSLATION ("translation" , 1, 0, 1.0F, 1.0F, 0.000F, 0.000F, 0.000F, 0.000F, 100.0F, 0.000F, 0.000F, 0.0F, "value is boolean"),
|
||||
;
|
||||
|
||||
public final String unlocalizedName;
|
||||
|
@ -147,15 +147,20 @@ public enum EnumForceFieldUpgrade implements IForceFieldUpgrade, IForceFieldUpgr
|
|||
|
||||
|
||||
@Override
|
||||
public int onEntityEffect(final float scaledValue, World world, final int x, final int y, final int z, Entity entity) {
|
||||
public int onEntityEffect(final float scaledValue, World world, final int projectorX, final int projectorY, final int projectorZ,
|
||||
final int blockX, final int blockY, final int blockZ, Entity entity) {
|
||||
if (scaledValue == 0.0F) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// common particle effects properties
|
||||
Vector3 origin = new Vector3(x + 0.5D, y + 0.5D, z + 0.5D);
|
||||
Vector3 direction = new Vector3(entity).subtract(origin).normalize();
|
||||
origin.translateFactor(direction, 0.6D);
|
||||
Vector3 v3Projector = new Vector3(projectorX + 0.5D, projectorY + 0.5D, projectorZ + 0.5D);
|
||||
double distanceCollision = v3Projector.distanceTo_square(new Vector3(blockX + 0.5D, blockY + 0.5D, blockZ + 0.5D));
|
||||
double distanceEntity = v3Projector.distanceTo_square(entity);
|
||||
Vector3 v3Entity = new Vector3(entity);
|
||||
Vector3 v3Direction = new Vector3(entity).subtract(v3Projector).normalize();
|
||||
v3Projector.translateFactor(v3Direction, 0.6D);
|
||||
v3Entity.translateFactor(v3Direction, -0.6D);
|
||||
|
||||
// entity classification
|
||||
int entityLevel = 0;
|
||||
|
@ -164,50 +169,99 @@ public enum EnumForceFieldUpgrade implements IForceFieldUpgrade, IForceFieldUpgr
|
|||
entityLevel = 0;
|
||||
} else if (entity instanceof EntityPlayer) {
|
||||
entityLevel = 4;
|
||||
} else if (entity instanceof EntityMob
|
||||
|| entity instanceof EntityGolem
|
||||
|| entity instanceof EntityFireball
|
||||
|| entity instanceof EntityTNTPrimed
|
||||
|| entity instanceof EntityThrowable
|
||||
|| entity instanceof EntityMinecart) {
|
||||
} else if ( entity instanceof EntityMob
|
||||
|| entity instanceof EntityGolem
|
||||
|| entity instanceof EntityFireball
|
||||
|| entity instanceof EntityTNTPrimed
|
||||
|| entity instanceof EntityThrowable
|
||||
|| entity instanceof EntityMinecart ) {
|
||||
entityLevel = 3;
|
||||
} else if (entity instanceof EntityLivingBase
|
||||
|| entity instanceof EntityXPOrb
|
||||
|| entity instanceof EntityBoat) {
|
||||
} else if ( entity instanceof EntityLivingBase
|
||||
|| entity instanceof EntityXPOrb
|
||||
|| entity instanceof EntityBoat ) {
|
||||
entityLevel = 2;
|
||||
} else if (entity instanceof EntityItem
|
||||
|| entity instanceof EntityArrow
|
||||
|| entity instanceof EntityFallingBlock) {
|
||||
} else if ( entity instanceof EntityItem
|
||||
|| entity instanceof EntityArrow
|
||||
|| entity instanceof EntityFallingBlock ) {
|
||||
entityLevel = 1;
|
||||
}
|
||||
}
|
||||
|
||||
double maxSpeed = scaledValue / (entityLevel / 4.0F) * ForceFieldSetup.FORCEFIELD_ACCELERATION_FACTOR;
|
||||
Vector3 motion = direction.clone().scale(maxSpeed); // new Vector3(entity.motionX, entity.motionY, entity.motionZ);
|
||||
double speed = Math.abs(scaledValue) / (entityLevel / 4.0F) * ForceFieldSetup.FORCEFIELD_ACCELERATION_FACTOR;
|
||||
Vector3 v3Motion = v3Direction.clone().scale(speed); // new Vector3(entity.motionX, entity.motionY, entity.motionZ);
|
||||
/*
|
||||
if (WarpDriveConfig.LOGGING_FORCEFIELD && WarpDrive.isDev) {
|
||||
WarpDrive.logger.info(this + " scaledValue " + scaledValue + " entityLevel " + entityLevel + " speed " + speed
|
||||
+ " entity " + v3Entity + " projector " + v3Projector + " direction " + v3Direction + " motion " + v3Motion + " entity " + entity);
|
||||
}
|
||||
/**/
|
||||
|
||||
// apply damages and particle effects
|
||||
switch(this) {
|
||||
case ATTRACTION:
|
||||
if (scaledValue <= 0.1F || entityLevel > scaledValue) {
|
||||
return 0;
|
||||
}
|
||||
// WarpDrive.logger.info("scaledValue " + scaledValue + " maxSpeed " + maxSpeed + " direction " + direction + " motion " + motion);
|
||||
motion.invert();
|
||||
v3Motion.invert();
|
||||
entity.fallDistance = 0.0F;
|
||||
entity.addVelocity(motion.x, motion.y, motion.z);
|
||||
entity.addVelocity(v3Motion.x, v3Motion.y, v3Motion.z);
|
||||
|
||||
PacketHandler.sendBeamPacket(world, origin, origin.clone().translate(motion),
|
||||
// pass through forcefield
|
||||
if (distanceCollision <= distanceEntity) {
|
||||
if (entity instanceof EntityLivingBase) {
|
||||
((EntityLivingBase)entity).setPositionAndUpdate(
|
||||
entity.posX - v3Direction.x * 2.0D,
|
||||
entity.posY - v3Direction.y * 2.0D,
|
||||
entity.posZ - v3Direction.z * 2.0D);
|
||||
} else {
|
||||
entity.setPosition(
|
||||
entity.posX - v3Direction.x * 2.0D,
|
||||
entity.posY - v3Direction.y * 2.0D,
|
||||
entity.posZ - v3Direction.z * 2.0D);
|
||||
}
|
||||
v3Entity.translateFactor(v3Direction, 2.0D);
|
||||
} else if (entity instanceof EntityPlayer) {
|
||||
((EntityLivingBase)entity).setPositionAndUpdate(
|
||||
entity.posX - v3Direction.x * 0.4D,
|
||||
entity.posY - v3Direction.y * 0.4D,
|
||||
entity.posZ - v3Direction.z * 0.4D);
|
||||
}
|
||||
|
||||
// visual effect
|
||||
PacketHandler.sendBeamPacket(world, v3Entity, v3Projector,
|
||||
0.2F, 0.4F, 0.7F, 10, 0, 50);
|
||||
return 10;
|
||||
|
||||
case REPULSION:
|
||||
if (scaledValue <= 0.1F || entityLevel > scaledValue) {
|
||||
if (scaledValue >= -0.1F || entityLevel > Math.abs(scaledValue)) {
|
||||
return 0;
|
||||
}
|
||||
WarpDrive.logger.info("scaledValue " + scaledValue + " maxSpeed " + maxSpeed + " direction " + direction + " motion " + motion);
|
||||
entity.fallDistance = 0.0F;
|
||||
entity.addVelocity(motion.x, motion.y, motion.z);
|
||||
entity.addVelocity(v3Motion.x, v3Motion.y, v3Motion.z);
|
||||
|
||||
PacketHandler.sendBeamPacket(world, origin, origin.clone().translate(motion),
|
||||
// pass through forcefield
|
||||
if (distanceCollision >= distanceEntity) {
|
||||
if (entity instanceof EntityLivingBase) {
|
||||
((EntityLivingBase)entity).setPositionAndUpdate(
|
||||
entity.posX + v3Direction.x * 2.0D,
|
||||
entity.posY + v3Direction.y * 2.0D,
|
||||
entity.posZ + v3Direction.z * 2.0D);
|
||||
} else {
|
||||
entity.setPosition(
|
||||
entity.posX + v3Direction.x * 2.0D,
|
||||
entity.posY + v3Direction.y * 2.0D,
|
||||
entity.posZ + v3Direction.z * 2.0D);
|
||||
}
|
||||
v3Entity.translateFactor(v3Direction, 2.0D);
|
||||
} else if (entity instanceof EntityPlayer) {
|
||||
((EntityLivingBase)entity).setPositionAndUpdate(
|
||||
entity.posX + v3Direction.x * 0.4D,
|
||||
entity.posY + v3Direction.y * 0.4D,
|
||||
entity.posZ + v3Direction.z * 0.4D);
|
||||
}
|
||||
|
||||
// visual effect
|
||||
PacketHandler.sendBeamPacket(world, v3Projector, v3Entity,
|
||||
0.2F, 0.4F, 0.7F, 10, 0, 50);
|
||||
return 10;
|
||||
|
||||
|
@ -217,8 +271,11 @@ public enum EnumForceFieldUpgrade implements IForceFieldUpgrade, IForceFieldUpgr
|
|||
}
|
||||
entity.attackEntityFrom(WarpDrive.damageCold, (300 - scaledValue) / 10);
|
||||
|
||||
direction.scale(0.20D);
|
||||
PacketHandler.sendSpawnParticlePacket(world, "snowshovel", origin, direction,
|
||||
// visual effect
|
||||
v3Direction.scale(0.20D);
|
||||
PacketHandler.sendBeamPacket(world, v3Projector, v3Entity,
|
||||
0.25F, 0.38F, 0.75F, 10, 0, 50);
|
||||
PacketHandler.sendSpawnParticlePacket(world, "snowshovel", v3Entity, v3Direction,
|
||||
0.20F + 0.10F * world.rand.nextFloat(), 0.25F + 0.25F * world.rand.nextFloat(), 0.60F + 0.30F * world.rand.nextFloat(),
|
||||
0.0F, 0.0F, 0.0F, 32);
|
||||
return 10;
|
||||
|
@ -232,13 +289,16 @@ public enum EnumForceFieldUpgrade implements IForceFieldUpgrade, IForceFieldUpgr
|
|||
}
|
||||
entity.attackEntityFrom(WarpDrive.damageWarm, (scaledValue - 300) / 100);
|
||||
|
||||
direction.scale(0.20D);
|
||||
PacketHandler.sendSpawnParticlePacket(world, "snowshovel", origin, direction,
|
||||
// visual effect
|
||||
v3Direction.scale(0.20D);
|
||||
PacketHandler.sendBeamPacket(world, v3Projector, v3Entity,
|
||||
0.95F, 0.52F, 0.38F, 10, 0, 50);
|
||||
PacketHandler.sendSpawnParticlePacket(world, "snowshovel", v3Entity, v3Direction,
|
||||
0.90F + 0.10F * world.rand.nextFloat(), 0.35F + 0.25F * world.rand.nextFloat(), 0.30F + 0.15F * world.rand.nextFloat(),
|
||||
0.0F, 0.0F, 0.0F, 32);
|
||||
/*
|
||||
direction.scale(0.10D);
|
||||
PacketHandler.sendSpawnParticlePacket(world, "flame", origin, direction,
|
||||
v3Direction.scale(0.10D);
|
||||
PacketHandler.sendSpawnParticlePacket(world, "flame", v3Projector, v3Direction,
|
||||
0.85F, 0.75F, 0.75F,
|
||||
0.0F, 0.0F, 0.0F, 32);
|
||||
/**/
|
||||
|
@ -250,8 +310,11 @@ public enum EnumForceFieldUpgrade implements IForceFieldUpgrade, IForceFieldUpgr
|
|||
}
|
||||
entity.attackEntityFrom(WarpDrive.damageShock, Math.abs(scaledValue));
|
||||
|
||||
direction.scale(0.15D);
|
||||
PacketHandler.sendSpawnParticlePacket(world, "fireworksSpark", origin, direction,
|
||||
// visual effect
|
||||
v3Direction.scale(0.15D);
|
||||
PacketHandler.sendBeamPacket(world, v3Projector, v3Entity,
|
||||
0.35F, 0.57F, 0.87F, 10, 0, 50);
|
||||
PacketHandler.sendSpawnParticlePacket(world, "fireworksSpark", v3Entity, v3Direction,
|
||||
0.20F + 0.30F * world.rand.nextFloat(), 0.50F + 0.15F * world.rand.nextFloat(), 0.75F + 0.25F * world.rand.nextFloat(),
|
||||
0.10F + 0.20F * world.rand.nextFloat(), 0.10F + 0.30F * world.rand.nextFloat(), 0.20F + 0.10F * world.rand.nextFloat(),
|
||||
32);
|
||||
|
|
|
@ -2,12 +2,10 @@ package cr0s.warpdrive.data;
|
|||
|
||||
import cr0s.warpdrive.WarpDrive;
|
||||
import cr0s.warpdrive.api.IBeamFrequency;
|
||||
import cr0s.warpdrive.block.forcefield.TileEntityForceFieldProjector;
|
||||
import cr0s.warpdrive.block.forcefield.TileEntityForceFieldRelay;
|
||||
import cr0s.warpdrive.config.WarpDriveConfig;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.world.WorldServer;
|
||||
import net.minecraftforge.common.util.ForgeDirection;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
@ -22,7 +20,7 @@ public class ForceFieldRegistry {
|
|||
|
||||
public static Set<TileEntity> getTileEntities(final int beamFrequency, WorldServer worldSource, final int x, final int y, final int z) {
|
||||
Set<GlobalPosition> setGlobalPositions = registry.get(beamFrequency);
|
||||
if (setGlobalPositions == null) {
|
||||
if (setGlobalPositions == null || worldSource == null) {
|
||||
return new HashSet<>();
|
||||
}
|
||||
// find all relevant tiles by world and frequency, keep relays in range as starting point
|
||||
|
@ -117,8 +115,7 @@ public class ForceFieldRegistry {
|
|||
if (setGlobalPositions == null) {
|
||||
setGlobalPositions = new HashSet<>(FORCE_FIELD_REGISTRY_DEFAULT_ENTRIES_PER_FREQUENCY);
|
||||
}
|
||||
for (Iterator<GlobalPosition> iterator = setGlobalPositions.iterator(); iterator.hasNext();) {
|
||||
GlobalPosition globalPosition = iterator.next();
|
||||
for (GlobalPosition globalPosition : setGlobalPositions) {
|
||||
if (globalPosition.equals(tileEntity)) {
|
||||
// already registered
|
||||
return;
|
||||
|
|
|
@ -34,8 +34,10 @@ public class ForceFieldSetup extends GlobalPosition {
|
|||
private static final float FORCEFIELD_MAX_PLACE_SPEED_BLOCKS_PER_SECOND = 4000;
|
||||
private static final float FORCEFIELD_UPGRADE_BOOST_FACTOR_PER_PROJECTOR_TIER = 0.50F;
|
||||
public static final float FORCEFIELD_UPGRADE_BOOST_FACTOR_PER_RELAY_TIER = 0.25F;
|
||||
public static final double FORCEFIELD_ACCELERATION_FACTOR = 0.01D;
|
||||
public static final double FORCEFIELD_ACCELERATION_FACTOR = 0.04D;
|
||||
public static final int FORCEFIELD_RELAY_RANGE = 20;
|
||||
private static final int FORCEFIELD_MAX_FACTOR_ENTITY_COST = 5;
|
||||
private static final double FORCEFIELD_TAU_FACTOR_ENTITY_COST = - Math.log(ForceFieldSetup.FORCEFIELD_MAX_FACTOR_ENTITY_COST);
|
||||
|
||||
public final int beamFrequency;
|
||||
public final byte tier;
|
||||
|
@ -51,10 +53,10 @@ public class ForceFieldSetup extends GlobalPosition {
|
|||
|
||||
public float scanSpeed;
|
||||
public float placeSpeed;
|
||||
public int startupEnergyCost;
|
||||
public int scanEnergyCost;
|
||||
public int placeEnergyCost;
|
||||
private int entityEnergyCost;
|
||||
public double startupEnergyCost;
|
||||
public double scanEnergyCost;
|
||||
public double placeEnergyCost;
|
||||
private double entityEnergyCost;
|
||||
|
||||
public float breaking_maxHardness;
|
||||
public float temperatureLevel;
|
||||
|
@ -82,14 +84,13 @@ public class ForceFieldSetup extends GlobalPosition {
|
|||
this.beamFrequency = beamFrequency;
|
||||
refresh();
|
||||
if (WarpDriveConfig.LOGGING_FORCEFIELD) {
|
||||
WarpDrive.logger.info("Force field projector energy costs:"
|
||||
+ " startup " + startupEnergyCost
|
||||
+ " / " + Math.round(startupEnergyCost + placeEnergyCost * placeSpeed * TileEntityForceFieldProjector.PROJECTOR_PROJECTION_UPDATE_TICKS / 20.0F)
|
||||
+ " scan " + scanEnergyCost
|
||||
+ " place " + placeEnergyCost
|
||||
+ " entity " + entityEnergyCost
|
||||
+ " speeds: scan " + scanSpeed
|
||||
+ " place " + placeSpeed);
|
||||
WarpDrive.logger.info(String.format("Force field projector energy costs: startup %.3f / %d scan %.3f place %.3f entity %.3f"
|
||||
+ " speeds: scan %.3f place %.3f"
|
||||
+ " sustain cost: scan %.3f place %.3f",
|
||||
startupEnergyCost, Math.round(startupEnergyCost + placeEnergyCost * placeSpeed * TileEntityForceFieldProjector.PROJECTOR_PROJECTION_UPDATE_TICKS / 20.0F),
|
||||
scanEnergyCost, placeEnergyCost, entityEnergyCost,
|
||||
scanSpeed, placeSpeed,
|
||||
(scanEnergyCost * scanSpeed), (placeEnergyCost * placeSpeed)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -214,10 +215,10 @@ public class ForceFieldSetup extends GlobalPosition {
|
|||
// set default coefficients, depending on projector
|
||||
scanSpeed = FORCEFIELD_BASE_SCAN_SPEED_BLOCKS_PER_SECOND * (isDoubleSided ? 2.1F : 1.0F);
|
||||
placeSpeed = FORCEFIELD_BASE_PLACE_SPEED_BLOCKS_PER_SECOND * (isDoubleSided ? 2.1F : 1.0F);
|
||||
float startupEnergyCost = 60.0F + 20.0F * tier;
|
||||
float scanEnergyCost = 1.0F + 1.0F * tier;
|
||||
float placeEnergyCost = 3.0F + 3.0F * tier;
|
||||
float entityEnergyCost = 2.0F;
|
||||
startupEnergyCost = 60.0F + 20.0F * tier;
|
||||
scanEnergyCost = 0.4F + 0.4F * tier;
|
||||
placeEnergyCost = 3.0F + 3.0F * tier;
|
||||
entityEnergyCost = 2.0F;
|
||||
if (isDoubleSided) {
|
||||
scanSpeed *= 2.1F;
|
||||
placeSpeed *= 2.1F;
|
||||
|
@ -246,17 +247,13 @@ public class ForceFieldSetup extends GlobalPosition {
|
|||
startupEnergyCost += entry.getKey().getStartupEnergyCost(scaledValue);
|
||||
scanEnergyCost += entry.getKey().getScanEnergyCost(scaledValue);
|
||||
placeEnergyCost += entry.getKey().getPlaceEnergyCost(scaledValue);
|
||||
entityEnergyCost += entry.getKey().getEntityEffectEnergyCost(scaledValue);
|
||||
entityEnergyCost += entry.getKey().getEntityEffectEnergyCost(scaledValue);
|
||||
}
|
||||
}
|
||||
|
||||
// finalize coefficients
|
||||
scanSpeed = Math.min(FORCEFIELD_MAX_SCAN_SPEED_BLOCKS_PER_SECOND, scanSpeed);
|
||||
placeSpeed = Math.min(FORCEFIELD_MAX_PLACE_SPEED_BLOCKS_PER_SECOND, placeSpeed);
|
||||
this.startupEnergyCost = Math.round(startupEnergyCost);
|
||||
this.scanEnergyCost = Math.round(scanEnergyCost);
|
||||
this.placeEnergyCost = Math.round(placeEnergyCost);
|
||||
this.entityEnergyCost = Math.round(entityEnergyCost);
|
||||
|
||||
// range is maximum distance
|
||||
double range = getScaledUpgrade(EnumForceFieldUpgrade.RANGE);
|
||||
|
@ -293,25 +290,25 @@ public class ForceFieldSetup extends GlobalPosition {
|
|||
thickness = 1.0F + getScaledUpgrade(EnumForceFieldUpgrade.THICKNESS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s @ DIM%d (%d %d %d) (%d %d %d) -> (%d %d %d)",
|
||||
getClass().getSimpleName(), dimensionId,
|
||||
x, y, z,
|
||||
vMin.x, vMin.y, vMin.z,
|
||||
vMax.x, vMax.y, vMax.z);
|
||||
public double getEntityEnergyCost(final int countEntityInteractions) {
|
||||
return entityEnergyCost * FORCEFIELD_MAX_FACTOR_ENTITY_COST * Math.exp(FORCEFIELD_TAU_FACTOR_ENTITY_COST / countEntityInteractions);
|
||||
}
|
||||
|
||||
public int onEntityEffect(World world, final int x, final int y, final int z, Entity entity) {
|
||||
public int onEntityEffect(World world, final int blockX, final int blockY, final int blockZ, Entity entity) {
|
||||
int countdown = 0;
|
||||
for (Map.Entry<IForceFieldUpgradeEffector, Float> entry : upgrades.entrySet()) {
|
||||
Float value = entry.getValue();
|
||||
if (entry.getKey() == EnumForceFieldUpgrade.COOLING || entry.getKey() == EnumForceFieldUpgrade.HEATING) {
|
||||
value = temperatureLevel;
|
||||
} else if (entry.getKey() == EnumForceFieldUpgrade.ATTRACTION || entry.getKey() == EnumForceFieldUpgrade.REPULSION) {
|
||||
value = accelerationLevel;
|
||||
TileEntity tileEntity = world.getTileEntity(x, y, z);
|
||||
if (tileEntity instanceof TileEntityForceFieldProjector) {
|
||||
if (((TileEntityForceFieldProjector)tileEntity).onEntityInteracted(entity.getUniqueID())) {
|
||||
for (Map.Entry<IForceFieldUpgradeEffector, Float> entry : upgrades.entrySet()) {
|
||||
Float value = entry.getValue();
|
||||
if (entry.getKey() == EnumForceFieldUpgrade.COOLING || entry.getKey() == EnumForceFieldUpgrade.HEATING) {
|
||||
value = temperatureLevel;
|
||||
} else if (entry.getKey() == EnumForceFieldUpgrade.ATTRACTION || entry.getKey() == EnumForceFieldUpgrade.REPULSION) {
|
||||
value = accelerationLevel;
|
||||
}
|
||||
countdown += entry.getKey().onEntityEffect(value, world, x, y, z, blockX, blockY, blockZ, entity);
|
||||
}
|
||||
}
|
||||
countdown += entry.getKey().onEntityEffect(value, world, x, y, z, entity);
|
||||
}
|
||||
return countdown;
|
||||
}
|
||||
|
@ -320,11 +317,20 @@ public class ForceFieldSetup extends GlobalPosition {
|
|||
assert(damageSource != null);
|
||||
TileEntity tileEntity = world.getTileEntity(this.x, this.y, this.z);
|
||||
if (tileEntity instanceof TileEntityForceFieldProjector) {
|
||||
float scaledDamage = damageLevel * entityEnergyCost / 20000.0F;
|
||||
int energyCost = (int)Math.floor(scaledDamage) + (world.rand.nextFloat() <= scaledDamage - Math.floor(scaledDamage) ? 1 : 0);
|
||||
((TileEntityForceFieldProjector)tileEntity).consumeEnergy(energyCost, false);
|
||||
double scaledDamage = damageLevel * entityEnergyCost / 20000.0D;
|
||||
WarpDrive.logger.info("Consuming " + scaledDamage);
|
||||
((TileEntityForceFieldProjector)tileEntity).consumeEnergy(scaledDamage, false);
|
||||
return 0;
|
||||
}
|
||||
return damageLevel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s @ DIM%d (%d %d %d) (%d %d %d) -> (%d %d %d)",
|
||||
getClass().getSimpleName(), dimensionId,
|
||||
x, y, z,
|
||||
vMin.x, vMin.y, vMin.z,
|
||||
vMax.x, vMax.y, vMax.z);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue