#Create Explosion that does not destroy block

8 messages · Page 1 of 1 (latest)

twilit flare
#

Sometimes you might not want to change the gamerule but still want a special explosion that spares blocks.

const getAABBofRadius = (centerX, centerY, centerZ, radius) => {
    const [minX, minY, minZ, maxX, maxY, maxZ] = [-1, 1].map(c => [centerX, centerY, centerZ].map(n => n + radius * c)).reduce((a, b) => a.concat(b))
    const aabb = AABB.of(minX, minY, minZ, maxX, maxY, maxZ)
    return aabb
}

/**
 * 
 * @param {Internal.Level_} level 
 * @param {number} x 
 * @param {number} y 
 * @param {number} z 
 * @param {number} power
 * @param {Internal.Entity_} exploder 
 * @param {boolean} spareExploder 
 */
function createPseudoExplosion(level, x ,y, z, power, exploder, spareExploder){
    const aabb = getAABBofRadius(x, y, z, power * 2)
    const explosionCenter = new Vec3d(x, y, z)
    const marker = level.createEntity("marker")
    marker.spawn()
    const explosionDamageSource = marker.damageSources().explosion(marker, exploder)
    level.spawnParticles("minecraft:explosion", false, x, y, z, 0, 0, 0, Math.floor(power/3), 1)
    level.runCommandSilent(`playsound minecraft:entity.generic.explode master @a ${x} ${y} ${z} 1 1`)
    level.getEntitiesWithin(aabb).forEach(entity => {
        if(spareExploder && entity.equals(exploder)) return;
        const entityPosisition = entity.position()
        const distance = explosionCenter.distanceTo(entityPosisition)
        const normalizedVec = entityPosisition.subtract(explosionCenter).normalize()
        const exposure =
        Array.from(Array(6).keys())
        .map(n => explosionCenter.add(normalizedVec.scale(n + 1)))
        .map(vec => level.getBlock(vec.x(), vec.y(), vec.z()).blockState.air)
        .map(b => b ? 1 : 0)
        .reduce((a, b) => a + b) / 6
        const maxBlastProt = entity.living 
        ? entity.armorSlots.map(item => item.getEnchantmentLevel("blast_protection")).reduce((a, b) => Math.max(a, b))
        : 0
        console.log(maxBlastProt) 
        const impact = (1 - distance / (2 * power)) * exposure * (1 - 0.15 * maxBlastProt)
        const damageAmount = impact * (impact + 1) * power * 7 + 1
        entity.attack(
            explosionDamageSource, 
            damageAmount
        )
        if(entity.alive){
            let velocity = normalizedVec.scale(exposure)
            entity.setMotion(
                entity.getMotionX() + velocity.x(),
                entity.getMotionY() + velocity.y(),
                entity.getMotionZ() + velocity.z()
            )
        }
    })
    marker.remove("discarded")
}
ItemEvents.rightClicked("stick", event=>{
    let {level, player, player:{x, y, z}} = event
    createPseudoExplosion(level, x, y, z, 3, player, true)
})
storm quest
#

What is the point of this? level.explosion already has a way to remove block damage

twilit flare
valid solar
#

e

cloud trench
#

this is actually useful for what I'm doing since I can both remove the particles and replace the explosion sound

#

but it would probably be better to use something other than marker

#

a combination of clip and projectileutils somehow

#

maybe something like this?

#1241228751883337739 message