Updated laser weapon balance

Fixed explosion never happening
Fixed laser stopping on entities
Added hull interaction with particle effect
This commit is contained in:
LemADEC 2016-04-17 03:38:58 +02:00
parent 43e9bc030a
commit 60d3016338
7 changed files with 326 additions and 56 deletions

View file

@ -0,0 +1,7 @@
package cr0s.warpdrive.api;
import net.minecraft.world.World;
public interface IHullBlock {
public void downgrade(World world, final int x, final int y, final int z);
}

View file

@ -24,6 +24,7 @@ import net.minecraft.util.Vec3;
import cpw.mods.fml.common.Optional;
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.api.IBeamFrequency;
import cr0s.warpdrive.api.IHullBlock;
import cr0s.warpdrive.block.weapon.BlockLaserCamera;
import cr0s.warpdrive.block.weapon.TileEntityLaserCamera;
import cr0s.warpdrive.config.Dictionary;
@ -146,10 +147,10 @@ public class TileEntityLaser extends TileEntityAbstractLaser implements IBeamFre
private void emitBeam(int beamEnergy) {
int energy = beamEnergy;
int beamLengthBlocks = clamp(0, WarpDriveConfig.LASER_CANNON_RANGE_MAX,
energy / WarpDriveConfig.LASER_CANNON_RANGE_ENERGY_PER_BLOCK);
if (energy == 0 || beamLengthBlocks < 1 || beamFrequency > 65000 || beamFrequency <= 0) {
int beamLengthBlocks = clamp(0, WarpDriveConfig.LASER_CANNON_RANGE_MAX, energy / 200);
if (energy == 0 || beamFrequency > 65000 || beamFrequency <= 0) {
if (WarpDriveConfig.LOGGING_WEAPON) {
WarpDrive.logger.info(this + " Beam canceled (energy " + energy + " over " + beamLengthBlocks + " blocks, beamFrequency " + beamFrequency + ")");
}
@ -246,6 +247,8 @@ public class TileEntityLaser extends TileEntityAbstractLaser implements IBeamFre
if (WarpDriveConfig.LOGGING_WEAPON) {
WarpDrive.logger.info("Entity is an invalid target (non-living " + entityId + ") " + mopEntity.entityHit);
}
// remove entity from hit list
entityHits.put(entityHitDistance, null);
continue;
}
if (WarpDriveConfig.LOGGING_WEAPON) {
@ -254,9 +257,9 @@ public class TileEntityLaser extends TileEntityAbstractLaser implements IBeamFre
}
// Consume energy
energy -= WarpDriveConfig.LASER_CANNON_ENTITY_HIT_ENERGY
+ ((blockHitDistance - distanceTravelled) * WarpDriveConfig.LASER_CANNON_ENERGY_LOSS_PER_BLOCK);
distanceTravelled = blockHitDistance;
energy *= getTransmittance(entityHitDistance - distanceTravelled);
energy -= WarpDriveConfig.LASER_CANNON_ENTITY_HIT_ENERGY;
distanceTravelled = entityHitDistance;
vHitPoint = new Vector3(mopEntity.hitVec);
if (energy <= 0) {
break;
@ -272,7 +275,7 @@ public class TileEntityLaser extends TileEntityAbstractLaser implements IBeamFre
mopEntity.entityHit.setDead();
}
if (energy > WarpDriveConfig.LASER_CANNON_ENTITY_HIT_ENERGY_THRESHOLD_FOR_EXPLOSION) {
if (energy > WarpDriveConfig.LASER_CANNON_ENTITY_HIT_EXPLOSION_ENERGY_THRESHOLD) {
float strength = (float)clamp(0.0D, WarpDriveConfig.LASER_CANNON_ENTITY_HIT_EXPLOSION_MAX_STRENGTH,
WarpDriveConfig.LASER_CANNON_ENTITY_HIT_EXPLOSION_BASE_STRENGTH + energy / WarpDriveConfig.LASER_CANNON_ENTITY_HIT_EXPLOSION_ENERGY_PER_STRENGTH);
worldObj.newExplosion(null, mopEntity.entityHit.posX, mopEntity.entityHit.posY, mopEntity.entityHit.posZ, strength, true, true);
@ -288,15 +291,33 @@ public class TileEntityLaser extends TileEntityAbstractLaser implements IBeamFre
// Laser went too far or no block hit
if (blockHitDistance >= beamLengthBlocks || blockHit == null) {
if (WarpDriveConfig.LOGGING_WEAPON) {
WarpDrive.logger.info("No more blocks to hit or too far: blockHitDistance is " + blockHitDistance + ", blockHit is " + blockHit);
}
vHitPoint = vReachPoint;
break;
}
Block block = worldObj.getBlock(blockHit.blockX, blockHit.blockY, blockHit.blockZ);
// int blockMeta = worldObj.getBlockMetadata(hit.blockX, hit.blockY, hit.blockZ);
float resistance = block.getExplosionResistance(null);
// get hardness and blast resistance
float hardness = -2.0F;
if (WarpDrive.fieldBlockHardness != null) {
// WarpDrive.fieldBlockHardness.setAccessible(true);
try {
hardness = (float)WarpDrive.fieldBlockHardness.get(block);
} catch (IllegalArgumentException | IllegalAccessException exception) {
exception.printStackTrace();
WarpDrive.logger.error("Unable to access block hardness value of " + block);
}
}
if (WarpDriveConfig.LOGGING_WEAPON) {
WarpDrive.logger.info("Block collision found at " + blockHit.blockX + " " + blockHit.blockY + " " + blockHit.blockZ
+ " with block " + block + " of hardness " + hardness);
}
if (block.isAssociatedBlock(Blocks.bedrock)) { // FIXME: should check block hardness instead?
// stop on unbreakable blocks
if (hardness < 0.0F) {
vHitPoint = new Vector3(blockHit.hitVec);
break;
}
@ -311,24 +332,71 @@ public class TileEntityLaser extends TileEntityAbstractLaser implements IBeamFre
}
}
// instantly break glass
if (block.getMaterial() == Material.glass) {
worldObj.setBlockToAir(blockHit.blockX, blockHit.blockY, blockHit.blockZ);
vHitPoint = new Vector3(blockHit.hitVec);
}
// Consume energy
energy -= WarpDriveConfig.LASER_CANNON_BLOCK_HIT_ENERGY
+ (resistance * WarpDriveConfig.LASER_CANNON_BLOCK_HIT_ENERGY_PER_BLOCK_RESISTANCE)
+ ((blockHitDistance - distanceTravelled) * WarpDriveConfig.LASER_CANNON_ENERGY_LOSS_PER_BLOCK);
distanceTravelled = blockHitDistance;
vHitPoint = new Vector3(blockHit.hitVec);
// Compute parameters
int energyCost = clamp(WarpDriveConfig.LASER_CANNON_BLOCK_HIT_ENERGY_MIN, WarpDriveConfig.LASER_CANNON_BLOCK_HIT_ENERGY_MAX,
Math.round(hardness * WarpDriveConfig.LASER_CANNON_BLOCK_HIT_ENERGY_PER_BLOCK_HARDNESS));
double absorptionChance = clamp(0.0D, WarpDriveConfig.LASER_CANNON_BLOCK_HIT_ABSORPTION_MAX,
hardness * WarpDriveConfig.LASER_CANNON_BLOCK_HIT_ABSORPTION_PER_BLOCK_HARDNESS);
do {
// Consume energy
energy *= getTransmittance(blockHitDistance - distanceTravelled);
energy -= energyCost;
distanceTravelled = blockHitDistance;
vHitPoint = new Vector3(blockHit.hitVec);
if (energy <= 0) {
if (WarpDriveConfig.LOGGING_WEAPON) {
WarpDrive.logger.info("Beam died out of energy");
}
break;
}
if (WarpDriveConfig.LOGGING_WEAPON) {
WarpDrive.logger.info("Beam energy down to " + energy);
}
// apply chance of absorption
if (worldObj.rand.nextDouble() > absorptionChance) {
break;
}
} while (true);
if (energy <= 0) {
break;
}
if (resistance >= WarpDriveConfig.LASER_CANNON_BLOCK_HIT_EXPLOSION_RESISTANCE_THRESHOLD) {
// apply hull effect
if (block instanceof IHullBlock) {
((IHullBlock)block).downgrade(worldObj, blockHit.blockX, blockHit.blockY, blockHit.blockZ);
// worldObj.newExplosion(null, blockHit.blockX, blockHit.blockY, blockHit.blockZ, 4, true, true);
Vector3 origin = new Vector3(
blockHit.blockX -0.93D * vDirection.x + worldObj.rand.nextFloat() - worldObj.rand.nextFloat(),
blockHit.blockY -0.93D * vDirection.y + worldObj.rand.nextFloat() - worldObj.rand.nextFloat(),
blockHit.blockZ -0.93D * vDirection.z + worldObj.rand.nextFloat() - worldObj.rand.nextFloat());
Vector3 direction = null;
direction = new Vector3(
-0.2D * vDirection.x + 0.05 * (worldObj.rand.nextFloat() - worldObj.rand.nextFloat()),
-0.2D * vDirection.y + 0.05 * (worldObj.rand.nextFloat() - worldObj.rand.nextFloat()),
-0.2D * vDirection.z + 0.05 * (worldObj.rand.nextFloat() - worldObj.rand.nextFloat()));
PacketHandler.sendSpawnParticlePacket(worldObj, "explode", origin, direction, r, g, b, 96);
WarpDrive.logger.info("Effect: block " + blockHit.blockX + " " + blockHit.blockY + " " + blockHit.blockZ
+ " effect at " + origin + " towards " + direction);
if (WarpDriveConfig.LOGGING_WEAPON) {
WarpDrive.logger.info("Hull absorbed remaining energy of " + energy);
}
break;
}
if (hardness >= WarpDriveConfig.LASER_CANNON_BLOCK_HIT_EXPLOSION_HARDNESS_THRESHOLD) {
float strength = (float)clamp(0.0D, WarpDriveConfig.LASER_CANNON_BLOCK_HIT_EXPLOSION_MAX_STRENGTH,
WarpDriveConfig.LASER_CANNON_BLOCK_HIT_EXPLOSION_BASE_STRENGTH + energy / WarpDriveConfig.LASER_CANNON_BLOCK_HIT_EXPLOSION_ENERGY_PER_STRENGTH);
if (WarpDriveConfig.LOGGING_WEAPON) {
WarpDrive.logger.info("Explosion triggered with strength " + strength);
}
worldObj.newExplosion(null, blockHit.blockX, blockHit.blockY, blockHit.blockZ, strength, true, true);
worldObj.setBlock(blockHit.blockX, blockHit.blockY, blockHit.blockZ, (worldObj.rand.nextBoolean()) ? Blocks.fire : Blocks.air);
} else {
@ -340,6 +408,25 @@ public class TileEntityLaser extends TileEntityAbstractLaser implements IBeamFre
beamLengthBlocks);
}
private double getTransmittance(final double distance) {
if (distance <= 0) {
return 1.0D;
}
boolean isInSpace = (worldObj.provider.dimensionId == WarpDriveConfig.G_SPACE_DIMENSION_ID);
boolean isInHyperSpace = (worldObj.provider.dimensionId == WarpDriveConfig.G_HYPERSPACE_DIMENSION_ID);
double attenuation;
if (isInSpace || isInHyperSpace) {
attenuation = WarpDriveConfig.LASER_CANNON_ENERGY_ATTENUATION_PER_VOID_BLOCK;
} else {
attenuation = WarpDriveConfig.LASER_CANNON_ENERGY_ATTENUATION_PER_AIR_BLOCK;
}
double transmittance = Math.exp(- attenuation * distance);
if (WarpDriveConfig.LOGGING_WEAPON) {
WarpDrive.logger.info("Transmittance over " + distance + " blocks is " + transmittance);
}
return transmittance;
}
public TreeMap<Double, MovingObjectPosition> raytraceEntities(Vector3 vSource, Vector3 vDirection, boolean collisionFlag, double reachDistance) {
final double raytraceTolerance = 2.0D;

View file

@ -5,13 +5,18 @@ import net.minecraft.block.BlockColored;
import net.minecraft.block.BlockGlass;
import net.minecraft.block.material.Material;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.api.IHullBlock;
import cr0s.warpdrive.config.WarpDriveConfig;
public class BlockHullGlass extends BlockColored {
public class BlockHullGlass extends BlockColored implements IHullBlock {
private int tier;
public BlockHullGlass(final int tier) {
super(Material.glass);
this.tier = tier;
setHardness(WarpDriveConfig.HULL_HARDNESS[tier - 1]);
setResistance(WarpDriveConfig.HULL_BLAST_RESISTANCE[tier - 1] * 5 / 3);
setStepSound(Block.soundTypeGlass);
@ -53,4 +58,14 @@ public class BlockHullGlass extends BlockColored {
public boolean renderAsNormalBlock() {
return false;
}
@Override
public void downgrade(World world, int x, int y, int z) {
int metadata = world.getBlockMetadata(x, y, z);
if (tier == 1) {
world.setBlockToAir(x, y, z);
} else {
world.setBlock(x, y, z, WarpDrive.blockHulls_plain[tier - 2], metadata, 2);
}
}
}

View file

@ -13,15 +13,19 @@ import net.minecraft.item.Item;
import net.minecraft.item.ItemDye;
import net.minecraft.item.ItemStack;
import net.minecraft.util.IIcon;
import net.minecraft.world.World;
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.api.IHullBlock;
import cr0s.warpdrive.config.WarpDriveConfig;
public class BlockHullPlain extends Block {
public class BlockHullPlain extends Block implements IHullBlock {
@SideOnly(Side.CLIENT)
private IIcon[] icons;
private int tier;
public BlockHullPlain(final int tier) {
super(Material.iron);
this.tier = tier;
setHardness(WarpDriveConfig.HULL_HARDNESS[tier - 1]);
setResistance(WarpDriveConfig.HULL_BLAST_RESISTANCE[tier - 1] * 5 / 3);
setStepSound(Block.soundTypeMetal);
@ -72,4 +76,14 @@ public class BlockHullPlain extends Block {
public MapColor getMapColor(int metadata) {
return MapColor.getMapColorForBlockColored(metadata);
}
@Override
public void downgrade(World world, int x, int y, int z) {
int metadata = world.getBlockMetadata(x, y, z);
if (tier == 1) {
world.setBlockToAir(x, y, z);
} else {
world.setBlock(x, y, z, WarpDrive.blockHulls_plain[tier - 2], metadata, 2);
}
}
}

View file

@ -195,33 +195,39 @@ public class WarpDriveConfig {
public static int LASER_MEDIUM_MAX_ENERGY_STORED = 100000;
// Laser Emitter
public static int LASER_CANNON_MAX_MEDIUMS_COUNT = 10;
public static int LASER_CANNON_MAX_LASER_ENERGY = 4000000;
public static int LASER_CANNON_EMIT_FIRE_DELAY_TICKS = 5;
public static int LASER_CANNON_EMIT_SCAN_DELAY_TICKS = 1;
// 1 main laser + 4 boosting lasers = 10 * 100k + 0.6 * 40 * 100k = 3.4M
public static int LASER_CANNON_MAX_MEDIUMS_COUNT = 10;
public static int LASER_CANNON_MAX_LASER_ENERGY = 3400000;
public static int LASER_CANNON_EMIT_FIRE_DELAY_TICKS = 5;
public static int LASER_CANNON_EMIT_SCAN_DELAY_TICKS = 1;
public static double LASER_CANNON_BOOSTER_BEAM_ENERGY_EFFICIENCY = 0.60D;
public static int LASER_CANNON_RANGE_ENERGY_PER_BLOCK = 5000;
public static int LASER_CANNON_RANGE_MAX = 500;
public static int LASER_CANNON_ENERGY_LOSS_PER_BLOCK = 500;
public static double LASER_CANNON_ENERGY_ATTENUATION_PER_AIR_BLOCK = 0.000200D;
public static double LASER_CANNON_ENERGY_ATTENUATION_PER_VOID_BLOCK = 0.000005D;
public static double LASER_CANNON_ENERGY_ATTENUATION_PER_BROKEN_BLOCK = 0.23D;
public static int LASER_CANNON_RANGE_MAX = 500;
public static int LASER_CANNON_ENTITY_HIT_SET_ON_FIRE_SECONDS = 20;
public static int LASER_CANNON_ENTITY_HIT_ENERGY = 15000;
public static int LASER_CANNON_ENTITY_HIT_BASE_DAMAGE = 3;
public static int LASER_CANNON_ENTITY_HIT_ENERGY_PER_DAMAGE = 30000;
public static int LASER_CANNON_ENTITY_HIT_MAX_DAMAGE = 100;
public static int LASER_CANNON_ENTITY_HIT_SET_ON_FIRE_SECONDS = 20;
public static int LASER_CANNON_ENTITY_HIT_ENERGY = 15000;
public static int LASER_CANNON_ENTITY_HIT_BASE_DAMAGE = 3;
public static int LASER_CANNON_ENTITY_HIT_ENERGY_PER_DAMAGE = 30000;
public static int LASER_CANNON_ENTITY_HIT_MAX_DAMAGE = 100;
public static int LASER_CANNON_ENTITY_HIT_ENERGY_THRESHOLD_FOR_EXPLOSION = 1000000;
public static float LASER_CANNON_ENTITY_HIT_EXPLOSION_BASE_STRENGTH = 4.0F;
public static int LASER_CANNON_ENTITY_HIT_EXPLOSION_ENERGY_PER_STRENGTH = 125000;
public static float LASER_CANNON_ENTITY_HIT_EXPLOSION_MAX_STRENGTH = 4.0F;
public static int LASER_CANNON_ENTITY_HIT_EXPLOSION_ENERGY_THRESHOLD = 900000;
public static float LASER_CANNON_ENTITY_HIT_EXPLOSION_BASE_STRENGTH = 4.0F;
public static int LASER_CANNON_ENTITY_HIT_EXPLOSION_ENERGY_PER_STRENGTH = 125000;
public static float LASER_CANNON_ENTITY_HIT_EXPLOSION_MAX_STRENGTH = 4.0F;
public static int LASER_CANNON_BLOCK_HIT_ENERGY = 70000;
public static int LASER_CANNON_BLOCK_HIT_ENERGY_PER_BLOCK_RESISTANCE = 1000;
public static double LASER_CANNON_BLOCK_HIT_EXPLOSION_RESISTANCE_THRESHOLD = 1200.0D; // obsidian is 2000 * 3 / 5 = 1200
public static float LASER_CANNON_BLOCK_HIT_EXPLOSION_BASE_STRENGTH = 8.0F;
public static int LASER_CANNON_BLOCK_HIT_EXPLOSION_ENERGY_PER_STRENGTH = 125000;
public static float LASER_CANNON_BLOCK_HIT_EXPLOSION_MAX_STRENGTH = 100F;
public static int LASER_CANNON_BLOCK_HIT_ENERGY_MIN = 75000;
public static int LASER_CANNON_BLOCK_HIT_ENERGY_PER_BLOCK_HARDNESS = 150000;
public static int LASER_CANNON_BLOCK_HIT_ENERGY_MAX = 750000;
public static double LASER_CANNON_BLOCK_HIT_ABSORPTION_PER_BLOCK_HARDNESS = 0.01;
public static double LASER_CANNON_BLOCK_HIT_ABSORPTION_MAX = 0.80;
public static float LASER_CANNON_BLOCK_HIT_EXPLOSION_HARDNESS_THRESHOLD = 5.0F;
public static float LASER_CANNON_BLOCK_HIT_EXPLOSION_BASE_STRENGTH = 8.0F;
public static int LASER_CANNON_BLOCK_HIT_EXPLOSION_ENERGY_PER_STRENGTH = 125000;
public static float LASER_CANNON_BLOCK_HIT_EXPLOSION_MAX_STRENGTH = 50F;
// Mining laser
// BuildCraft quarry values for reference
@ -564,12 +570,14 @@ public class WarpDriveConfig {
LASER_CANNON_BOOSTER_BEAM_ENERGY_EFFICIENCY = clamp(0.01D, 10.0D,
config.get("laser_cannon", "booster_beam_energy_efficiency", LASER_CANNON_BOOSTER_BEAM_ENERGY_EFFICIENCY, "Energy factor applied from boosting to main laser").getDouble(0.6D));
LASER_CANNON_RANGE_ENERGY_PER_BLOCK = clamp(1, LASER_CANNON_MAX_LASER_ENERGY / 10,
config.get("laser_cannon", "range_energy_per_block", LASER_CANNON_RANGE_ENERGY_PER_BLOCK, "Energy required per block distance").getInt());
LASER_CANNON_ENERGY_ATTENUATION_PER_AIR_BLOCK = clamp(0.0D, 0.1D,
config.get("laser_cannon", "energy_attenueation_per_air_block", LASER_CANNON_ENERGY_ATTENUATION_PER_AIR_BLOCK, "Energy attenuation when going through air blocks (on a planet or any gaz in space)").getDouble());
LASER_CANNON_ENERGY_ATTENUATION_PER_VOID_BLOCK = clamp(0.0D, 0.1D,
config.get("laser_cannon", "energy_attenueation_per_air_block", LASER_CANNON_ENERGY_ATTENUATION_PER_VOID_BLOCK, "Energy attenuation when going through void blocks (in space or hyperspace)").getDouble());
LASER_CANNON_ENERGY_ATTENUATION_PER_BROKEN_BLOCK = clamp(0.0D, 1.0D,
config.get("laser_cannon", "energy_attenueation_per_air_block", LASER_CANNON_ENERGY_ATTENUATION_PER_BROKEN_BLOCK, "Energy attenuation when going through a broken block").getDouble());
LASER_CANNON_RANGE_MAX = clamp(64, 512,
config.get("laser_cannon", "range_max", LASER_CANNON_RANGE_MAX, "Maximum distance travelled").getInt());
LASER_CANNON_ENERGY_LOSS_PER_BLOCK = clamp(0, Integer.MAX_VALUE,
config.get("laser_cannon", "energy_loss_per_block", LASER_CANNON_ENERGY_LOSS_PER_BLOCK, "Energy consummed per distance travelled").getInt());
LASER_CANNON_ENTITY_HIT_SET_ON_FIRE_SECONDS = clamp(0, 300,
config.get("laser_cannon", "entity_hit_set_on_fire_seconds", LASER_CANNON_ENTITY_HIT_SET_ON_FIRE_SECONDS, "Duration of fire effect on entity hit (in seconds)").getInt());
@ -583,8 +591,8 @@ public class WarpDriveConfig {
LASER_CANNON_ENTITY_HIT_MAX_DAMAGE = clamp(0, Integer.MAX_VALUE,
config.get("laser_cannon", "entity_hit_max_damage", LASER_CANNON_ENTITY_HIT_MAX_DAMAGE, "Maximum damage to entity hit, set to 0 to disable damage completly").getInt());
LASER_CANNON_ENTITY_HIT_ENERGY_THRESHOLD_FOR_EXPLOSION = clamp(0, Integer.MAX_VALUE,
config.get("laser_cannon", "entity_hit_energy_threshold_for_explosion", LASER_CANNON_ENTITY_HIT_ENERGY_THRESHOLD_FOR_EXPLOSION, "Minimum energy to cause explosion effect").getInt());
LASER_CANNON_ENTITY_HIT_EXPLOSION_ENERGY_THRESHOLD = clamp(0, Integer.MAX_VALUE,
config.get("laser_cannon", "entity_hit_energy_threshold_for_explosion", LASER_CANNON_ENTITY_HIT_EXPLOSION_ENERGY_THRESHOLD, "Minimum energy to cause explosion effect").getInt());
LASER_CANNON_ENTITY_HIT_EXPLOSION_BASE_STRENGTH = (float) clamp(0.0D, 100.0D,
config.get("laser_cannon", "entity_hit_explosion_base_strength", LASER_CANNON_ENTITY_HIT_EXPLOSION_BASE_STRENGTH, "Explosion base strength, 4 is Vanilla TNT").getDouble());
LASER_CANNON_ENTITY_HIT_EXPLOSION_ENERGY_PER_STRENGTH = clamp(1, Integer.MAX_VALUE,
@ -592,14 +600,20 @@ public class WarpDriveConfig {
LASER_CANNON_ENTITY_HIT_EXPLOSION_MAX_STRENGTH = (float) clamp(0.0D, 1000.0D,
config.get("laser_cannon", "entity_hit_explosion_max_strength", LASER_CANNON_ENTITY_HIT_EXPLOSION_MAX_STRENGTH, "Maximum explosion strength, set to 0 to disable explosion completly").getDouble());
LASER_CANNON_BLOCK_HIT_ENERGY = clamp(0, Integer.MAX_VALUE,
config.get("laser_cannon", "block_hit_energy", LASER_CANNON_BLOCK_HIT_ENERGY, "Base energy consummed from hitting a block").getInt());
LASER_CANNON_BLOCK_HIT_ENERGY_PER_BLOCK_RESISTANCE = clamp(0, Integer.MAX_VALUE,
config.get("laser_cannon", "block_hit_energy_per_block_resistance", LASER_CANNON_BLOCK_HIT_ENERGY_PER_BLOCK_RESISTANCE, "Energy consummed per explosive resistance points").getInt());
LASER_CANNON_BLOCK_HIT_ENERGY_MIN = clamp(0, Integer.MAX_VALUE,
config.get("laser_cannon", "block_hit_energy_min", LASER_CANNON_BLOCK_HIT_ENERGY_MIN, "Minimum energy required for breaking a block").getInt());
LASER_CANNON_BLOCK_HIT_ENERGY_PER_BLOCK_HARDNESS = clamp(0, Integer.MAX_VALUE,
config.get("laser_cannon", "block_hit_energy_per_block_hardness", LASER_CANNON_BLOCK_HIT_ENERGY_PER_BLOCK_HARDNESS, "Energy cost per block hardness for breaking a block").getInt());
LASER_CANNON_BLOCK_HIT_ENERGY_MAX = clamp(0, Integer.MAX_VALUE,
config.get("laser_cannon", "block_hit_energy_max", LASER_CANNON_BLOCK_HIT_ENERGY_MAX, "Maximum energy required for breaking a block").getInt());
LASER_CANNON_BLOCK_HIT_ABSORPTION_PER_BLOCK_HARDNESS = clamp(0.0D, 1.0D,
config.get("laser_cannon", "block_hit_absorption_per_block_hardness", LASER_CANNON_BLOCK_HIT_ABSORPTION_PER_BLOCK_HARDNESS, "Probability of energy absorption (i.e. block not breaking) per block hardness. Set to 1.0 to always break the block.").getDouble());
LASER_CANNON_BLOCK_HIT_ABSORPTION_MAX = clamp(0.0D, 1.0D,
config.get("laser_cannon", "block_hit_absorption_max", LASER_CANNON_BLOCK_HIT_ABSORPTION_MAX, "Maximum probability of energy absorption (i.e. block not breaking)").getDouble());
LASER_CANNON_BLOCK_HIT_EXPLOSION_RESISTANCE_THRESHOLD = clamp(0.0D, 1000000.0D,
config.get("laser_cannon", "block_hit_explosion_resistance_threshold", LASER_CANNON_BLOCK_HIT_EXPLOSION_RESISTANCE_THRESHOLD,
"Block explosion resistance threshold to cause an explosion").getDouble());
LASER_CANNON_BLOCK_HIT_EXPLOSION_HARDNESS_THRESHOLD = (float) clamp(0.0D, 10000.0D,
config.get("laser_cannon", "block_hit_explosion_hardness_threshold", LASER_CANNON_BLOCK_HIT_EXPLOSION_HARDNESS_THRESHOLD,
"Minimum block hardness required to cause an explosion").getDouble());
LASER_CANNON_BLOCK_HIT_EXPLOSION_BASE_STRENGTH = (float) clamp(0.0D, 1000.0D,
config.get("laser_cannon", "block_hit_explosion_base_strength", LASER_CANNON_BLOCK_HIT_EXPLOSION_BASE_STRENGTH, "Explosion base strength, 4 is Vanilla TNT").getDouble());
LASER_CANNON_BLOCK_HIT_EXPLOSION_ENERGY_PER_STRENGTH = clamp(1, Integer.MAX_VALUE,

View file

@ -0,0 +1,120 @@
package cr0s.warpdrive.network;
import java.nio.charset.StandardCharsets;
import net.minecraft.client.Minecraft;
import net.minecraft.client.particle.EntityExplodeFX;
import net.minecraft.client.particle.EntityFX;
import net.minecraft.world.World;
import io.netty.buffer.ByteBuf;
import cpw.mods.fml.client.FMLClientHandler;
import cpw.mods.fml.common.network.simpleimpl.IMessage;
import cpw.mods.fml.common.network.simpleimpl.IMessageHandler;
import cpw.mods.fml.common.network.simpleimpl.MessageContext;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.config.WarpDriveConfig;
import cr0s.warpdrive.data.Vector3;
public class MessageSpawnParticle implements IMessage, IMessageHandler<MessageSpawnParticle, IMessage> {
private String type;
private Vector3 origin;
private Vector3 direction;
private float red;
private float green;
private float blue;
public MessageSpawnParticle() {
// required on receiving side
}
public MessageSpawnParticle(final String type, final Vector3 origin, final Vector3 direction, final float red, final float green, final float blue) {
this.type = type;
this.origin = origin;
this.direction = direction;
this.red = red;
this.green = green;
this.blue = blue;
}
@Override
public void fromBytes(ByteBuf buffer) {
int typeSize = buffer.readByte();
WarpDrive.logger.info("1: " + buffer.readerIndex() + " typeSize " + typeSize);
type = buffer.toString(buffer.readerIndex(), typeSize, StandardCharsets.US_ASCII);
WarpDrive.logger.info("2: " + buffer.readerIndex() + " type " + type);
buffer.skipBytes(typeSize);
WarpDrive.logger.info("3: " + buffer.readerIndex());
double x = buffer.readDouble();
double y = buffer.readDouble();
double z = buffer.readDouble();
origin = new Vector3(x, y, z);
x = buffer.readDouble();
y = buffer.readDouble();
z = buffer.readDouble();
direction = new Vector3(x, y, z);
red = buffer.readFloat();
green = buffer.readFloat();
blue = buffer.readFloat();
}
@Override
public void toBytes(ByteBuf buffer) {
buffer.writeByte(type.length());
buffer.writeBytes(type.getBytes(StandardCharsets.US_ASCII), 0, type.length());
buffer.writeDouble(origin.x);
buffer.writeDouble(origin.y);
buffer.writeDouble(origin.z);
buffer.writeDouble(direction.x);
buffer.writeDouble(direction.y);
buffer.writeDouble(direction.z);
buffer.writeFloat(red);
buffer.writeFloat(green);
buffer.writeFloat(blue);
}
@SideOnly(Side.CLIENT)
private void handle(World worldObj) {
// Directly spawn particle as per RenderGlobal.doSpawnParticle, bypassing range check
// adjust color as needed
for (int i = 0; i < 5; i++) {
direction = new Vector3(
direction.x + 0.05 * (worldObj.rand.nextFloat() - worldObj.rand.nextFloat()),
direction.y + 0.05 * (worldObj.rand.nextFloat() - worldObj.rand.nextFloat()),
direction.z + 0.05 * (worldObj.rand.nextFloat() - worldObj.rand.nextFloat()));
EntityFX effect = new EntityExplodeFX(worldObj, origin.x, origin.y, origin.z,
direction.x, direction.y, direction.z); // TODO: implements other effects
if (red >= 0.0F && green >= 0.0F && blue >= 0.0F) {
effect.setRBGColorF(red, green, blue);
}
FMLClientHandler.instance().getClient().effectRenderer.addEffect(effect);
}
WarpDrive.logger.info("Executing particle effect '" + type + "' from " + origin + " toward " + direction
+ " as RGB " + red + " " + green + " " + blue);
}
@Override
@SideOnly(Side.CLIENT)
public IMessage onMessage(MessageSpawnParticle messageSpawnParticle, MessageContext context) {
// skip in case player just logged in
if (Minecraft.getMinecraft().theWorld == null) {
WarpDrive.logger.error("WorldObj is null, ignoring beam packet");
return null;
}
if (WarpDriveConfig.LOGGING_EFFECTS) {
WarpDrive.logger.info("Received particle effect '" + messageSpawnParticle.type + "' from " + messageSpawnParticle.origin + " toward " + messageSpawnParticle.direction
+ " as RGB " + messageSpawnParticle.red + " " + messageSpawnParticle.green + " " + messageSpawnParticle.blue);
}
messageSpawnParticle.handle(Minecraft.getMinecraft().theWorld);
return null; // no response
}
}

View file

@ -31,11 +31,12 @@ public class PacketHandler {
public static void init() {
// Forge packets
simpleNetworkManager.registerMessage(MessageBeamEffect.class, MessageBeamEffect.class, 0, Side.CLIENT);
simpleNetworkManager.registerMessage(MessageBeamEffect.class , MessageBeamEffect.class , 0, Side.CLIENT);
simpleNetworkManager.registerMessage(MessageVideoChannel.class , MessageVideoChannel.class , 1, Side.CLIENT);
simpleNetworkManager.registerMessage(MessageCloak.class , MessageCloak.class , 2, Side.CLIENT);
simpleNetworkManager.registerMessage(MessageCloak.class , MessageCloak.class , 2, Side.CLIENT);
simpleNetworkManager.registerMessage(MessageSpawnParticle.class, MessageSpawnParticle.class, 3, Side.CLIENT);
simpleNetworkManager.registerMessage(MessageTargeting.class , MessageTargeting.class , 100, Side.SERVER);
simpleNetworkManager.registerMessage(MessageTargeting.class , MessageTargeting.class , 100, Side.SERVER);
// Entity packets for 'uncloaking' entities
try {
@ -93,6 +94,18 @@ public class PacketHandler {
}
}
// Forced particle effect sent to client side
public static void sendSpawnParticlePacket(World worldObj, final String type, Vector3 origin, Vector3 direction, float red, float green, float blue, int radius) {
assert(!worldObj.isRemote);
MessageSpawnParticle beamSpawnParticle = new MessageSpawnParticle(type, origin, direction, red, green, blue);
// small beam are sent relative to beam center
simpleNetworkManager.sendToAllAround(beamSpawnParticle, new TargetPoint(
worldObj.provider.dimensionId, origin.x, origin.y, origin.z, radius));
}
// Monitor/Laser/Camera updating its video channel to client side
public static void sendVideoChannelPacket(int dimensionId, int xCoord, int yCoord, int zCoord, int videoChannel) {
MessageVideoChannel videoChannelMessage = new MessageVideoChannel(xCoord, yCoord, zCoord, videoChannel);