satomakiya123
@satomakiya123 (hbm mc)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

ミサイルが目標座標に正確に到達しません

解決したいこと

https://github.com/HbmMods/Hbm-s-Nuclear-Tech-GIT
Hbm-s-Nuclear-Tech modのソースコードを少し改造し、ミサイルの速度をマッハ10にしてみたのですが、速度が速すぎるせいなのか、ミサイルが目標座標とはずれて起爆します

該当するソースコード(元のソースと同じではなく、少し書き換えています)

ファイル名
EntityMissileBaseNT

package com.hbm.entity.missile;

import java.util.ArrayList;
import java.util.List;

import com.hbm.entity.logic.IChunkLoader;
import com.hbm.entity.projectile.EntityThrowableInterp;
import com.hbm.explosion.ExplosionLarge;
import com.hbm.explosion.vanillant.ExplosionVNT;
import com.hbm.explosion.vanillant.standard.BlockAllocatorStandard;
import com.hbm.explosion.vanillant.standard.BlockMutatorFire;
import com.hbm.explosion.vanillant.standard.BlockProcessorStandard;
import com.hbm.explosion.vanillant.standard.EntityProcessorCross;
import com.hbm.explosion.vanillant.standard.PlayerProcessorStandard;
import com.hbm.items.weapon.ItemMissile;
import com.hbm.main.MainRegistry;
import com.hbm.util.TrackerUtil;

import api.hbm.entity.IRadarDetectableNT;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.entity.EntityTrackerEntry;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.DamageSource;
import net.minecraft.util.MathHelper;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.util.Vec3;
import net.minecraft.world.ChunkCoordIntPair;
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
import net.minecraftforge.common.ForgeChunkManager;
import net.minecraftforge.common.ForgeChunkManager.Ticket;
import net.minecraftforge.common.ForgeChunkManager.Type;

public abstract class EntityMissileBaseNT extends EntityThrowableInterp implements IChunkLoader, IRadarDetectableNT {

	public int startX;
	public int startZ;
	public int targetX;
	public int targetZ;
	public double velocity;
	public double decelY;
	public double accelXZ;
	public boolean isCluster = false;
	private Ticket loaderTicket;
	public int health = 50;

	private static final double MAX_VELOCITY = 170.0;

	public EntityMissileBaseNT(World world) {
		super(world);
		this.ignoreFrustumCheck = true;
		startX = (int) posX;
		startZ = (int) posZ;
		targetX = (int) posX;
		targetZ = (int) posZ;
	}

	public EntityMissileBaseNT(World world, float x, float y, float z, int a, int b) {
		super(world);
		this.ignoreFrustumCheck = true;
		this.setLocationAndAngles(x, y, z, 0, 0);
		startX = (int) x;
		startZ = (int) z;
		targetX = a;
		targetZ = b;
		this.motionY = 2;

		Vec3 vector = Vec3.createVectorHelper(targetX - startX, 0, targetZ - startZ);
		accelXZ = decelY = 1 / vector.lengthVector();
		decelY *= 2;
		velocity = 0;

		this.rotationYaw = (float) (Math.atan2(targetX - posX, targetZ - posZ) * 180.0D / Math.PI);

		this.setSize(1.5F, 1.5F);
	}

	/** Auto-generates radar blip level and all that from the item */
	public abstract ItemStack getMissileItemForInfo();

	@Override
	public boolean canBeSeenBy(Object radar) {
		return true;
	}

	@Override
	public boolean paramsApplicable(RadarScanParams params) {
		if(!params.scanMissiles) return false;
		return true;
	}

	@Override
	public boolean suppliesRedstone(RadarScanParams params) {
		if(params.smartMode && this.motionY >= 0) return false;
		return true;
	}

	@Override
	protected void entityInit() {
		super.entityInit();
		init(ForgeChunkManager.requestTicket(MainRegistry.instance, worldObj, Type.ENTITY));
		this.dataWatcher.addObject(3, new Byte((byte) 5));
	}

	@Override
	protected double motionMult() {
		return velocity;
	}

	@Override
	public boolean doesImpactEntities() {
		return false;
	}

	@Override
	public void onUpdate() {
		this.lastTickPosX = this.posX;
		this.lastTickPosY = this.posY;
		this.lastTickPosZ = this.posZ;
		super.onUpdate();

		// 速度をマッハ10に向けて調整
		if (velocity < MAX_VELOCITY) {
			velocity += MathHelper.clamp_double(this.ticksExisted / 60D * 50D, 0, 50); // 加速スピードを変更
		}

		if (!worldObj.isRemote) {
			if (hasPropulsion()) {
				this.motionY -= decelY * velocity;

				Vec3 vector = Vec3.createVectorHelper(targetX - startX, 0, targetZ - startZ);
				vector = vector.normalize();
				vector.xCoord *= accelXZ;
				vector.zCoord *= accelXZ;

				if (motionY > 0) {
					motionX += vector.xCoord * velocity;
					motionZ += vector.zCoord * velocity;
				}

				if (motionY < 0) {
					motionX -= vector.xCoord * velocity;
					motionZ -= vector.zCoord * velocity;
				}
			} else {
				motionX *= 0.99;
				motionZ *= 0.99;

				if (motionY > -1.5)
					motionY -= 0.05;
			}

			this.rotationYaw = (float) (Math.atan2(targetX - posX, targetZ - posZ) * 180.0D / Math.PI);
			float f2 = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ);
			for (this.rotationPitch = (float) (Math.atan2(this.motionY, f2) * 180.0D / Math.PI) - 90; this.rotationPitch - this.prevRotationPitch < -180.0F; this.prevRotationPitch -= 360.0F)
				;

			EntityTrackerEntry tracker = TrackerUtil.getTrackerEntry((WorldServer) worldObj, this.getEntityId());
			if (tracker != null) tracker.lastYaw += 100;

			loadNeighboringChunks((int) Math.floor(posX / 16), (int) Math.floor(posZ / 16));

			if (isCloseToTarget()) {
				explodeAtTarget();
				this.setDead();
				return;
			}


		} else {
			this.spawnContrail();
		}

		while (this.rotationPitch - this.prevRotationPitch >= 180.0F) this.prevRotationPitch += 360.0F;
		while (this.rotationYaw - this.prevRotationYaw < -180.0F) this.prevRotationYaw -= 360.0F;
		while (this.rotationYaw - this.prevRotationYaw >= 180.0F) this.prevRotationYaw += 360.0F;
	}


	private boolean isCloseToTarget() {
		double threshold = 0.5; // 許容誤差
		return Math.abs(this.posX - targetX) < threshold &&
			Math.abs(this.posY - this.worldObj.getHeightValue(targetX, targetZ)) < threshold &&
			Math.abs(this.posZ - targetZ) < threshold;
	}

	private void explodeAtTarget() {
		this.worldObj.createExplosion(this, this.posX, this.posY, this.posZ, 5.0F, true);
	}


	public boolean hasPropulsion() {
		return true;
	}

	protected void spawnContrail() {
		this.spawnContraolWithOffset(0, 0, 0);
	}

	protected void spawnContraolWithOffset(double offsetX, double offsetY, double offsetZ) {
		Vec3 vec = Vec3.createVectorHelper(this.lastTickPosX - this.posX, this.lastTickPosY - this.posY, this.lastTickPosZ - this.posZ);
		double len = vec.lengthVector();
		vec = vec.normalize();
		Vec3 thrust = Vec3.createVectorHelper(0, 1, 0);
		thrust.rotateAroundZ(this.rotationPitch * (float) Math.PI / 180F);
		thrust.rotateAroundY((this.rotationYaw + 90) * (float) Math.PI / 180F);

		for(int i = 0; i < Math.max(Math.min(len, 10), 1); i++) {
			double j = i - len;
			NBTTagCompound data = new NBTTagCompound();
			data.setDouble("posX", posX - vec.xCoord * j + offsetX);
			data.setDouble("posY", posY - vec.yCoord * j + offsetY);
			data.setDouble("posZ", posZ - vec.zCoord * j + offsetZ);
			data.setString("type", "missileContrail");
			data.setFloat("scale", this.getContrailScale());
			data.setDouble("moX", -thrust.xCoord);
			data.setDouble("moY", -thrust.yCoord);
			data.setDouble("moZ", -thrust.zCoord);
			data.setInteger("maxAge", 60 + rand.nextInt(20));
			MainRegistry.proxy.effectNT(data);
		}
	}

	protected float getContrailScale() {
		return 1F;
	}

	@Override
	public void readEntityFromNBT(NBTTagCompound nbt) {
		super.readEntityFromNBT(nbt);
		motionX = nbt.getDouble("moX");
		motionY = nbt.getDouble("moY");
		motionZ = nbt.getDouble("moZ");
		posX = nbt.getDouble("poX");
		posY = nbt.getDouble("poY");
		posZ = nbt.getDouble("poZ");
		decelY = nbt.getDouble("decel");
		accelXZ = nbt.getDouble("accel");
		targetX = nbt.getInteger("tX");
		targetZ = nbt.getInteger("tZ");
		startX = nbt.getInteger("sX");
		startZ = nbt.getInteger("sZ");
		velocity = nbt.getDouble("veloc");
	}

	@Override
	public void writeEntityToNBT(NBTTagCompound nbt) {
		super.writeEntityToNBT(nbt);
		nbt.setDouble("moX", motionX);
		nbt.setDouble("moY", motionY);
		nbt.setDouble("moZ", motionZ);
		nbt.setDouble("poX", posX);
		nbt.setDouble("poY", posY);
		nbt.setDouble("poZ", posZ);
		nbt.setDouble("decel", decelY);
		nbt.setDouble("accel", accelXZ);
		nbt.setInteger("tX", targetX);
		nbt.setInteger("tZ", targetZ);
		nbt.setInteger("sX", startX);
		nbt.setInteger("sZ", startZ);
		nbt.setDouble("veloc", velocity);
	}

	public boolean canBeCollidedWith() {
		return true;
	}

	public boolean attackEntityFrom(DamageSource source, float amount) {
		if(this.isEntityInvulnerable()) {
			return false;
		} else {
			if(this.health > 0 && !this.worldObj.isRemote) {
				health -= amount;

				if(this.health <= 0) {
					this.killMissile();
				}
			}

			return true;
		}
	}

	protected void killMissile() {
		if(!this.isDead) {
			this.setDead();
			ExplosionLarge.explode(worldObj, posX, posY, posZ, 5, true, false, true);
			ExplosionLarge.spawnShrapnelShower(worldObj, posX, posY, posZ, motionX, motionY, motionZ, 15, 0.075);
			ExplosionLarge.spawnMissileDebris(worldObj, posX, posY, posZ, motionX, motionY, motionZ, 0.25, getDebris(), getDebrisRareDrop());
		}
	}

	@Override
	@SideOnly(Side.CLIENT)
	public boolean isInRangeToRenderDist(double distance) {
		return true;
	}

	@Override
	protected void onImpact(MovingObjectPosition mop) {
		if(mop != null && mop.typeOfHit == mop.typeOfHit.BLOCK) {
			this.onImpact();
			this.setDead();
		}
	}

	public abstract void onImpact();
	public abstract List<ItemStack> getDebris();
	public abstract ItemStack getDebrisRareDrop();
	public void cluster() { }

	@Override
	public double getGravityVelocity() {
		return 0.0D;
	}

	@Override
	protected float getAirDrag() {
		return 1F;
	}

	@Override
	protected float getWaterDrag() {
		return 1F;
	}

	@Override
	public void init(Ticket ticket) {
		if(!worldObj.isRemote) {

			if(ticket != null) {

				if(loaderTicket == null) {

					loaderTicket = ticket;
					loaderTicket.bindEntity(this);
					loaderTicket.getModData();
				}

				ForgeChunkManager.forceChunk(loaderTicket, new ChunkCoordIntPair(chunkCoordX, chunkCoordZ));
			}
		}
	}

	List<ChunkCoordIntPair> loadedChunks = new ArrayList<ChunkCoordIntPair>();

	public void loadNeighboringChunks(int newChunkX, int newChunkZ) {
		if(!worldObj.isRemote && loaderTicket != null) {

			clearChunkLoader();

			loadedChunks.clear();
			loadedChunks.add(new ChunkCoordIntPair(newChunkX, newChunkZ));
			//loadedChunks.add(new ChunkCoordIntPair(newChunkX + (int) Math.floor((this.posX + this.motionX * this.motionMult()) / 16D), newChunkZ + (int) Math.floor((this.posZ + this.motionZ * this.motionMult()) / 16D)));

			for(ChunkCoordIntPair chunk : loadedChunks) {
				ForgeChunkManager.forceChunk(loaderTicket, chunk);
			}
		}
	}

	@Override
	public void setDead() {
		super.setDead();
		this.clearChunkLoader();
	}


	public void clearChunkLoader() {
		// チャンクの強制読み込み解除を防ぎ、ミサイルが目標に到達するまで消えないように変更
		if (!worldObj.isRemote && loaderTicket != null) {
			// 何もしない、チャンクの強制読み込みを保持
		}
	}
	public void explodeStandard(float strength, int resolution, boolean fire) {
		ExplosionVNT xnt = new ExplosionVNT(worldObj, posX, posY, posZ, strength);
		xnt.setBlockAllocator(new BlockAllocatorStandard(resolution));
		xnt.setBlockProcessor(new BlockProcessorStandard().setNoDrop().withBlockEffect(fire ? new BlockMutatorFire() : null));
		xnt.setEntityProcessor(new EntityProcessorCross(7.5D).withRangeMod(2));
		xnt.setPlayerProcessor(new PlayerProcessorStandard());
		xnt.explode();
	}

	@Override
	public String getUnlocalizedName() {
		ItemStack item = this.getMissileItemForInfo();
		if(item != null && item.getItem() instanceof ItemMissile) {
			ItemMissile missile = (ItemMissile) item.getItem();
			switch(missile.tier) {
			case TIER0: return "radar.target.tier0";
			case TIER1: return "radar.target.tier1";
			case TIER2: return "radar.target.tier2";
			case TIER3: return "radar.target.tier3";
			case TIER4: return "radar.target.tier4";
			default: return "Unknown";
			}
		}

		return "Unknown";
	}

	@Override
	public int getBlipLevel() {
		ItemStack item = this.getMissileItemForInfo();
		if(item != null && item.getItem() instanceof ItemMissile) {
			ItemMissile missile = (ItemMissile) item.getItem();
			switch(missile.tier) {
			case TIER0: return IRadarDetectableNT.TIER0;
			case TIER1: return IRadarDetectableNT.TIER1;
			case TIER2: return IRadarDetectableNT.TIER2;
			case TIER3: return IRadarDetectableNT.TIER3;
			case TIER4: return IRadarDetectableNT.TIER4;
			default: return IRadarDetectableNT.SPECIAL;
			}
		}

		return IRadarDetectableNT.SPECIAL;
	}
}

ファイル名
EntityMissileBase

package com.hbm.entity.missile;

import com.hbm.calc.EasyLocation;

import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.entity.projectile.EntityThrowable;
import net.minecraft.init.Blocks;
import net.minecraft.util.MathHelper;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.world.World;

public class EntityMissileBase extends EntityThrowable {

	EasyLocation origin;
	EasyLocation loc0;
	EasyLocation loc1;
	EasyLocation loc2;
	EasyLocation loc3;
	EasyLocation loc4;
	EasyLocation loc5;
	EasyLocation loc6;
	EasyLocation loc7;
	EasyLocation target;

	public int phase = 0;

	public int targetPoint = 0;
	public int lengthX;
	public int lengthZ;
	public double lengthFlight;
	public int baseHeight = 50;

	public double missileSpeed = 170.0; // 秒速3400m相当

	public EntityMissileBase(World p_i1776_1_) {
		super(p_i1776_1_);
		this.ignoreFrustumCheck = true;
	}

	public EntityMissileBase(World p_i1582_1_, int x, int z, double a, double b, double c) {
		super(p_i1582_1_);
		this.ignoreFrustumCheck = true;
		this.posX = a;
		this.posY = b;
		this.posZ = c;

		this.motionY = 0.1;

		lengthX = (int) (x - this.posX);
		lengthZ = (int) (z - this.posZ);
		lengthFlight = Math.sqrt(Math.pow(lengthX, 2) + Math.pow(lengthZ, 2));

		origin = new EasyLocation(this.posX, this.posY, this.posZ);

		loc0 = new EasyLocation(this.posX, this.posY + baseHeight, this.posZ);
		loc1 = new EasyLocation(this.posX + lengthX/lengthFlight * 10, this.posY + baseHeight + 20, this.posZ + lengthZ/lengthFlight * 10);
		loc2 = new EasyLocation(this.posX + lengthX/lengthFlight * 30, this.posY + baseHeight + 40, this.posZ + lengthZ/lengthFlight * 30);
		loc3 = new EasyLocation(this.posX + lengthX/lengthFlight * 50, this.posY + baseHeight + 50, this.posZ + lengthZ/lengthFlight * 50);

		loc4 = new EasyLocation(x - (lengthX/lengthFlight * 50), this.posY + baseHeight + 50, z - (lengthZ/lengthFlight * 50));
		loc5 = new EasyLocation(x - (lengthX/lengthFlight * 30), this.posY + baseHeight + 40, z - (lengthZ/lengthFlight * 30));
		loc6 = new EasyLocation(x - (lengthX/lengthFlight * 10), this.posY + baseHeight + 20, z - (lengthZ/lengthFlight * 10));
		loc7 = new EasyLocation(x, this.posY + baseHeight, z);

		target = new EasyLocation(x, 0, z);
	}

	protected void freePizzaGoddammit(EasyLocation loc) {
		double x = loc.posX - this.posX;
		double y = loc.posY - this.posY;
		double z = loc.posZ - this.posZ;
		lengthFlight = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2) + Math.pow(z, 2));

		this.motionX = x / this.lengthFlight * missileSpeed;
		this.motionY = y / this.lengthFlight * missileSpeed;
		this.motionZ = z / this.lengthFlight * missileSpeed;
	}

	protected void rotation() {
		float f2 = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ);
		this.rotationYaw = (float)(Math.atan2(this.motionX, this.motionZ) * 180.0D / Math.PI);

		for (this.rotationPitch = (float)(Math.atan2(this.motionY, f2) * 180.0D / Math.PI) - 90; this.rotationPitch - this.prevRotationPitch < -180.0F; this.prevRotationPitch -= 360.0F);

		while (this.rotationPitch - this.prevRotationPitch >= 180.0F) this.prevRotationPitch += 360.0F;
		while (this.rotationYaw - this.prevRotationYaw < -180.0F) this.prevRotationYaw -= 360.0F;
		while (this.rotationYaw - this.prevRotationYaw >= 180.0F) this.prevRotationYaw += 360.0F;
	}

	@Override
	public void onUpdate() {
		this.posX += this.motionX;
		this.posY += this.motionY;
		this.posZ += this.motionZ;

		this.rotation();

		switch(phase) {
			case 0:
				if(loc0 != null) {
					freePizzaGoddammit(loc0);
					if(isCloseToLocation(loc0)) {
						this.phase = 1;
					}
				}
				break;
			case 1:
				if(loc1 != null) {
					freePizzaGoddammit(loc1);
					if(isCloseToLocation(loc1)) {
						this.phase = 2;
					}
				}
				break;
			case 2:
				if(loc2 != null) {
					freePizzaGoddammit(loc2);
					if(isCloseToLocation(loc2)) {
						this.phase = 3;
					}
				}
				break;
			case 3:
				if(loc3 != null) {
					freePizzaGoddammit(loc3);
					if(isCloseToLocation(loc3)) {
						this.phase = 4;
					}
				}
				break;
			case 4:
				if(loc4 != null) {
					freePizzaGoddammit(loc4);
					if(isCloseToLocation(loc4)) {
						this.phase = 5;
					}
				}
				break;
			case 5:
				if(loc5 != null) {
					freePizzaGoddammit(loc5);
					if(isCloseToLocation(loc5)) {
						this.phase = 6;
					}
				}
				break;
			case 6:
				if(loc6 != null) {
					freePizzaGoddammit(loc6);
					if(isCloseToLocation(loc6)) {
						this.phase = 7;
					}
				}
				break;
			case 7:
				if(loc7 != null) {
					freePizzaGoddammit(loc7);
					if(isCloseToLocation(loc7)) {
						this.phase = 8;
					}
				}
				break;
			case 8:
				if(target != null) {
					freePizzaGoddammit(target);
					if(isCloseToLocation(target)) {
						explodeAtTarget();
						this.setDead();
					}
				}
				break;
		}

		if(this.worldObj.getBlock((int)this.posX, (int)this.posY, (int)this.posZ) != Blocks.air &&
			this.worldObj.getBlock((int)this.posX, (int)this.posY, (int)this.posZ) != Blocks.water &&
			this.worldObj.getBlock((int)this.posX, (int)this.posY, (int)this.posZ) != Blocks.flowing_water) {
			if(!this.worldObj.isRemote) {
				this.worldObj.createExplosion(this, this.posX, this.posY, this.posZ, 5.0F, true);
			}
			this.setDead();
		}
	}

	private boolean isCloseToLocation(EasyLocation loc) {
		double threshold = 0.5; // 許容誤差
		return Math.abs(loc.posX - this.posX) < threshold &&
			Math.abs(loc.posY - this.posY) < threshold &&
			Math.abs(loc.posZ - this.posZ) < threshold;
	}

	private void explodeAtTarget() {
		this.worldObj.createExplosion(this, this.posX, this.posY, this.posZ, 5.0F, true);
	}

	@Override
	protected void onImpact(MovingObjectPosition p_70184_1_) {

	}

	@Override
	@SideOnly(Side.CLIENT)
	public boolean isInRangeToRenderDist(double distance) {
		return distance < 25000;
	}
}

自分で試したこと

私は、ChatGPTの意見を参考にし、書き換えてみましたがそれでも目標とはズレて到達します

0

No Answers yet.

Your answer might help someone💌