允许获取命中的OBB部件

This commit is contained in:
17146 2025-06-20 16:27:07 +08:00 committed by Light_Quanta
parent 869687d58a
commit 46e7c2b5e0
No known key found for this signature in database
GPG key ID: 11A39A1B8C890959
5 changed files with 57 additions and 15 deletions

View file

@ -0,0 +1,21 @@
package com.atsuishio.superbwarfare.entity.mixin;
import com.atsuishio.superbwarfare.tools.OBB;
import net.minecraft.world.entity.Entity;
public interface OBBHitter {
static OBBHitter getInstance(Entity entity) {
return (OBBHitter) entity;
}
/**
* 获取当前命中部分
*/
OBB.Part sbw$getCurrentHitPart();
/**
* 设置当前命中部分
*/
void sbw$setCurrentHitPart(OBB.Part part);
}

View file

@ -2,6 +2,7 @@ package com.atsuishio.superbwarfare.entity.vehicle.base;
import com.atsuishio.superbwarfare.Mod; import com.atsuishio.superbwarfare.Mod;
import com.atsuishio.superbwarfare.data.vehicle.VehicleData; import com.atsuishio.superbwarfare.data.vehicle.VehicleData;
import com.atsuishio.superbwarfare.entity.mixin.OBBHitter;
import com.atsuishio.superbwarfare.entity.vehicle.DroneEntity; import com.atsuishio.superbwarfare.entity.vehicle.DroneEntity;
import com.atsuishio.superbwarfare.entity.vehicle.damage.DamageModifier; import com.atsuishio.superbwarfare.entity.vehicle.damage.DamageModifier;
import com.atsuishio.superbwarfare.entity.vehicle.weapon.VehicleWeapon; import com.atsuishio.superbwarfare.entity.vehicle.weapon.VehicleWeapon;
@ -48,6 +49,7 @@ import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.Pose; import net.minecraft.world.entity.Pose;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.projectile.AbstractArrow; import net.minecraft.world.entity.projectile.AbstractArrow;
import net.minecraft.world.entity.projectile.Projectile;
import net.minecraft.world.entity.vehicle.DismountHelper; import net.minecraft.world.entity.vehicle.DismountHelper;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
@ -428,6 +430,12 @@ public abstract class VehicleEntity extends Entity {
repairCoolDown = maxRepairCoolDown(); repairCoolDown = maxRepairCoolDown();
} }
// TODO 这里可以获取击中的部位给需要的载具加一个部位受伤方法
if (source.getDirectEntity() instanceof Projectile projectile) {
OBBHitter accessor = OBBHitter.getInstance(projectile);
// System.out.println(accessor.sbw$getCurrentHitPart());
}
this.onHurt(computedAmount, source.getEntity(), true); this.onHurt(computedAmount, source.getEntity(), true);
return super.hurt(source, computedAmount); return super.hurt(source, computedAmount);
} }
@ -449,10 +457,8 @@ public abstract class VehicleEntity extends Entity {
if (attacker != null) { if (attacker != null) {
Vec3 toVec = new Vec3(getX(), getY() + getBbHeight() / 2, getZ()).vectorTo(attacker.position()).normalize(); Vec3 toVec = new Vec3(getX(), getY() + getBbHeight() / 2, getZ()).vectorTo(attacker.position()).normalize();
float angle = (float) java.lang.Math.abs(VectorTool.calculateAngle(this.position().vectorTo(attacker.position()), this.getViewVector(1))); return (float) Math.max(1f - multiply * toVec.dot(getViewVector(1)), 0.5f);
return (float) java.lang.Math.max(1f - multiply * toVec.dot(getViewVector(1)), 0.5f);
} }
return 1; return 1;
} }

View file

@ -1,6 +1,8 @@
package com.atsuishio.superbwarfare.mixins; package com.atsuishio.superbwarfare.mixins;
import com.atsuishio.superbwarfare.entity.mixin.OBBHitter;
import com.atsuishio.superbwarfare.entity.vehicle.base.MobileVehicleEntity; import com.atsuishio.superbwarfare.entity.vehicle.base.MobileVehicleEntity;
import com.atsuishio.superbwarfare.tools.OBB;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
@ -11,7 +13,7 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(Entity.class) @Mixin(Entity.class)
public class EntityMixin { public class EntityMixin implements OBBHitter {
/** /**
* From Automobility * From Automobility
@ -38,6 +40,19 @@ public class EntityMixin {
} }
} }
@Unique
public OBB.Part sbw$currentHitPart;
@Override
public OBB.Part sbw$getCurrentHitPart() {
return this.sbw$currentHitPart;
}
@Override
public void sbw$setCurrentHitPart(OBB.Part part) {
this.sbw$currentHitPart = part;
}
// TODO 优化后续逻辑 // TODO 优化后续逻辑
// @Redirect(method = "turn(DD)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;setXRot(F)V", ordinal = 1)) // @Redirect(method = "turn(DD)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;setXRot(F)V", ordinal = 1))
// public void turn(Entity instance, float pXRot) { // public void turn(Entity instance, float pXRot) {

View file

@ -1,10 +1,9 @@
package com.atsuishio.superbwarfare.mixins; package com.atsuishio.superbwarfare.mixins;
import com.atsuishio.superbwarfare.entity.OBBEntity; import com.atsuishio.superbwarfare.entity.OBBEntity;
import com.atsuishio.superbwarfare.entity.vehicle.Bmp2Entity; import com.atsuishio.superbwarfare.entity.mixin.OBBHitter;
import com.atsuishio.superbwarfare.init.ModParticleTypes; import com.atsuishio.superbwarfare.init.ModParticleTypes;
import com.atsuishio.superbwarfare.init.ModSounds; import com.atsuishio.superbwarfare.init.ModSounds;
import com.atsuishio.superbwarfare.tools.OBB;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.particles.ParticleTypes; import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
@ -25,7 +24,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.Optional; import java.util.Optional;
import java.util.function.Predicate; import java.util.function.Predicate;
import static com.atsuishio.superbwarfare.entity.vehicle.Bmp2Entity.TURRET_DAMAGED;
import static com.atsuishio.superbwarfare.tools.ParticleTool.sendParticle; import static com.atsuishio.superbwarfare.tools.ParticleTool.sendParticle;
@Mixin(ProjectileUtil.class) @Mixin(ProjectileUtil.class)
@ -47,6 +45,9 @@ public class ProjectileUtilMixin {
double d1 = pStartVec.distanceToSqr(new Vec3(optional.get())); double d1 = pStartVec.distanceToSqr(new Vec3(optional.get()));
if (d1 < Double.MAX_VALUE) { if (d1 < Double.MAX_VALUE) {
EntityHitResult hitResult = new EntityHitResult(entity, new Vec3(optional.get())); EntityHitResult hitResult = new EntityHitResult(entity, new Vec3(optional.get()));
var acc = OBBHitter.getInstance(pProjectile);
acc.sbw$setCurrentHitPart(obb.part());
cir.setReturnValue(hitResult); cir.setReturnValue(hitResult);
if (pLevel instanceof ServerLevel serverLevel && pProjectile.getDeltaMovement().lengthSqr() > 0.01) { if (pLevel instanceof ServerLevel serverLevel && pProjectile.getDeltaMovement().lengthSqr() > 0.01) {
Vec3 hitPos = hitResult.getLocation(); Vec3 hitPos = hitResult.getLocation();
@ -55,9 +56,6 @@ public class ProjectileUtilMixin {
sendParticle(serverLevel, ParticleTypes.SMOKE, hitPos.x, hitPos.y, hitPos.z, 2, 0, 0, 0, 0.01, false); sendParticle(serverLevel, ParticleTypes.SMOKE, hitPos.x, hitPos.y, hitPos.z, 2, 0, 0, 0, 0.01, false);
} }
} }
if (obbEntity instanceof Bmp2Entity bmp2 && obb.part() == OBB.Part.TURRET) {
bmp2.getEntityData().set(TURRET_DAMAGED, true);
}
} }
} }
} }

View file

@ -15,6 +15,7 @@ import java.util.Optional;
* @param center 旋转中心 * @param center 旋转中心
* @param extents 三个轴向上的半长 * @param extents 三个轴向上的半长
* @param rotation 旋转 * @param rotation 旋转
* @param part 部件
*/ */
public record OBB(Vector3f center, Vector3f extents, Quaternionf rotation, Part part) { public record OBB(Vector3f center, Vector3f extents, Quaternionf rotation, Part part) {
@ -257,10 +258,11 @@ public record OBB(Vector3f center, Vector3f extents, Quaternionf rotation, Part
} }
public enum Part { public enum Part {
WHEEL_LEFT(), EMPTY,
WHEEL_RIGHT(), WHEEL_LEFT,
TURRET(), WHEEL_RIGHT,
ENGINE(), TURRET,
BODY(); ENGINE,
BODY
} }
} }