Explosive Hammer
This commit is contained in:
parent
f0076aca99
commit
8760fc3ec0
@ -8,7 +8,6 @@ import net.minecraft.advancements.critereon.InventoryChangeTrigger
|
||||
import net.minecraft.world.item.DyeColor
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraftforge.common.data.ExistingFileHelper
|
||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||
import ru.dbotthepony.mc.otm.core.registryName
|
||||
import ru.dbotthepony.mc.otm.datagen.lang.MatteryLanguageProvider
|
||||
import ru.dbotthepony.mc.otm.datagen.modLocation
|
||||
@ -16,6 +15,7 @@ import ru.dbotthepony.mc.otm.registry.MItemTags
|
||||
import ru.dbotthepony.mc.otm.registry.MItems
|
||||
import ru.dbotthepony.mc.otm.registry.MRegistry
|
||||
import ru.dbotthepony.mc.otm.triggers.BlackHoleTrigger
|
||||
import ru.dbotthepony.mc.otm.triggers.NailedEntityTrigger
|
||||
import java.util.function.Consumer
|
||||
|
||||
fun addAdvancements(serializer: Consumer<Advancement>, existingFileHelper: ExistingFileHelper, lang: MatteryLanguageProvider) {
|
||||
@ -553,4 +553,18 @@ fun addAdvancements(serializer: Consumer<Advancement>, existingFileHelper: Exist
|
||||
.addCriterion("essence1", criterion(MItems.ESSENCE_CAPSULE))
|
||||
.addCriterion("essence2", criterion(MItems.ESSENCE_DRIVE))
|
||||
.save(serializer, modLocation("regular/essence_capsule"), existingFileHelper)
|
||||
|
||||
AdvancementBuilder()
|
||||
.parent(root)
|
||||
.display(
|
||||
itemStack = ItemStack(MItems.EXPLOSIVE_HAMMER).also { MItems.EXPLOSIVE_HAMMER.prime(it) },
|
||||
title = translation.add("explosive_hammer", "I Did It Like This") {
|
||||
russian("Я сделал это вот так")
|
||||
},
|
||||
description = translation.add("explosive_hammer.desc", "Nail down something (or someone)") {
|
||||
russian("Пригвоздите что-либо (или кого-либо)")
|
||||
}
|
||||
)
|
||||
.addCriterion("damage", NailedEntityTrigger.Instance())
|
||||
.save(serializer, modLocation("regular/explosive_hammer"), existingFileHelper)
|
||||
}
|
||||
|
@ -348,6 +348,11 @@ private fun death(provider: MatteryLanguageProvider) {
|
||||
death("otm_emp.player", "%2\$s blew fuzes of %1\$s")
|
||||
death("otm_emp.player.item", "%2\$s blew fuzes of %1\$s using %3\$s")
|
||||
|
||||
death(MRegistry.DAMAGE_EXPLOSIVE_HAMMER_NAME, "%1\$s's fun time with hammer is over")
|
||||
death(MRegistry.DAMAGE_HAMMER_NAIL_NAME, "%1\$s got nailed")
|
||||
death(MRegistry.DAMAGE_HAMMER_NAIL_NAME + ".player", "%1\$s got nailed by %\$2")
|
||||
death(MRegistry.DAMAGE_HAMMER_NAIL_NAME + ".player.item", "%1\$s got nailed by %2\$s using %3\$s")
|
||||
|
||||
death(MRegistry.DAMAGE_EXOPACK_PROBE_ID, "%1\$s couldn't handle spinal surgery")
|
||||
death("${MRegistry.DAMAGE_EXOPACK_PROBE_ID}.player", "%1\$s couldn't handle spinal surgery whilst fighting %2\$s")
|
||||
}
|
||||
@ -447,6 +452,12 @@ private fun blocks(provider: MatteryLanguageProvider) {
|
||||
|
||||
private fun items(provider: MatteryLanguageProvider) {
|
||||
with(provider.english) {
|
||||
add(MItems.EXPLOSIVE_HAMMER, "Explosive Hammer")
|
||||
add(MItems.EXPLOSIVE_HAMMER, "desc", "For those who feel bored")
|
||||
add(MItems.EXPLOSIVE_HAMMER, "primed", "Primed!")
|
||||
add(MItems.EXPLOSIVE_HAMMER, "not_primed0", "Not primed")
|
||||
add(MItems.EXPLOSIVE_HAMMER, "not_primed1", "Prime at crafting table with little of gunpowder and nugget payload")
|
||||
|
||||
add(MItems.EXOPACK_PROBE, "Exopack Probe")
|
||||
add(MItems.ExopackUpgrades.INVENTORY_UPGRADE_CREATIVE, "Creative Exopack Inventory Upgrade")
|
||||
add(MItems.ExopackUpgrades.CRAFTING_UPGRADE, "Exopack Crafting Upgrade")
|
||||
|
@ -355,6 +355,11 @@ private fun death(provider: MatteryLanguageProvider) {
|
||||
death("otm_emp.player", "%2\$s выбил все предохранители %1\$s")
|
||||
death("otm_emp.player.item", "%2\$s выбил все предохранители %1\$s используя %3\$s")
|
||||
|
||||
death(MRegistry.DAMAGE_EXPLOSIVE_HAMMER_NAME, "Время развлечений у %1\$s с молотком подошло к концу")
|
||||
death(MRegistry.DAMAGE_HAMMER_NAIL_NAME, "%1\$s был пригвождён")
|
||||
death(MRegistry.DAMAGE_HAMMER_NAIL_NAME + ".player", "%1\$s был пригвождён %2\$s")
|
||||
death(MRegistry.DAMAGE_HAMMER_NAIL_NAME + ".player.item", "%1\$s был пригвождён %2\$s используя %3\$s")
|
||||
|
||||
death(MRegistry.DAMAGE_EXOPACK_PROBE_ID, "%1\$s не выдержал спинную хирургию")
|
||||
death("${MRegistry.DAMAGE_EXOPACK_PROBE_ID}.player", "%1\$s не выдержал спинную хирургию пока сражался с %2\$s")
|
||||
}
|
||||
@ -454,6 +459,12 @@ private fun blocks(provider: MatteryLanguageProvider) {
|
||||
|
||||
private fun items(provider: MatteryLanguageProvider) {
|
||||
with(provider.russian) {
|
||||
add(MItems.EXPLOSIVE_HAMMER, "Молоток-убийца")
|
||||
add(MItems.EXPLOSIVE_HAMMER, "desc", "Для тех, кому стало скучно")
|
||||
add(MItems.EXPLOSIVE_HAMMER, "primed", "Заряжен!")
|
||||
add(MItems.EXPLOSIVE_HAMMER, "not_primed0", "Не заряжен")
|
||||
add(MItems.EXPLOSIVE_HAMMER, "not_primed1", "Для зарядки добавьте немного пороха и наконечник-самородок")
|
||||
|
||||
add(MItems.EXOPACK_PROBE, "Маяк экзопака")
|
||||
add(MItems.ExopackUpgrades.INVENTORY_UPGRADE_CREATIVE, "Творческое обновление инвентаря экзопака")
|
||||
add(MItems.ExopackUpgrades.CRAFTING_UPGRADE, "Обновление сетки крафта экзопака")
|
||||
|
@ -15,6 +15,7 @@ import ru.dbotthepony.mc.otm.registry.MItems
|
||||
import ru.dbotthepony.mc.otm.registry.MRegistry
|
||||
import ru.dbotthepony.mc.otm.core.registryName
|
||||
import ru.dbotthepony.mc.otm.datagen.modLocation
|
||||
import ru.dbotthepony.mc.otm.recipe.ExplosiveHammerPrimingRecipe
|
||||
import ru.dbotthepony.mc.otm.recipe.UpgradeRecipe
|
||||
import java.util.function.Consumer
|
||||
|
||||
@ -331,4 +332,13 @@ fun addCraftingTableRecipes(consumer: Consumer<FinishedRecipe>) {
|
||||
.unlockedBy(MItemTags.HARDENED_GLASS_PANES)
|
||||
.unlockedBy(MItemTags.TRITANIUM_INGOTS)
|
||||
.build(consumer)
|
||||
|
||||
consumer.accept(ExplosiveHammerPrimingRecipe(modLocation("hammer_priming"), Ingredient.of(Tags.Items.NUGGETS_IRON)).finishedRecipe)
|
||||
|
||||
MatteryRecipe(MItems.EXPLOSIVE_HAMMER, category = RecipeCategory.COMBAT)
|
||||
.rowB(Tags.Items.INGOTS_IRON)
|
||||
.rowAB(Tags.Items.INGOTS_IRON, Tags.Items.RODS_WOODEN)
|
||||
.rowB(Tags.Items.RODS_WOODEN)
|
||||
.unlockedBy(Items.FLINT_AND_STEEL)
|
||||
.build(consumer)
|
||||
}
|
||||
|
@ -46,6 +46,7 @@ import ru.dbotthepony.mc.otm.config.ServerCompatConfig;
|
||||
import ru.dbotthepony.mc.otm.config.ServerConfig;
|
||||
import ru.dbotthepony.mc.otm.config.ToolsConfig;
|
||||
import ru.dbotthepony.mc.otm.core.math.Decimal;
|
||||
import ru.dbotthepony.mc.otm.item.ExplosiveHammerItem;
|
||||
import ru.dbotthepony.mc.otm.item.ItemTritaniumArmor;
|
||||
import ru.dbotthepony.mc.otm.item.QuantumBatteryItem;
|
||||
import ru.dbotthepony.mc.otm.item.weapon.AbstractWeaponItem;
|
||||
@ -191,6 +192,8 @@ public final class OverdriveThatMatters {
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, EnderTeleporterFeature.Companion::onEntityDeath);
|
||||
EVENT_BUS.addListener(EventPriority.HIGH, ItemTritaniumArmor.Companion::onHurt);
|
||||
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, ExplosiveHammerItem.Companion::onLeftClickBlock);
|
||||
|
||||
MatteryPlayerNetworkChannel.INSTANCE.register();
|
||||
MenuNetworkChannel.INSTANCE.register();
|
||||
WeaponNetworkChannel.INSTANCE.register();
|
||||
|
@ -9,6 +9,7 @@ import net.minecraftforge.registries.DeferredRegister;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters;
|
||||
import ru.dbotthepony.mc.otm.recipe.EnergyContainerRecipe;
|
||||
import ru.dbotthepony.mc.otm.recipe.ExplosiveHammerPrimingRecipe;
|
||||
import ru.dbotthepony.mc.otm.recipe.PlatePressRecipe;
|
||||
import ru.dbotthepony.mc.otm.recipe.PlatePressRecipeFactory;
|
||||
import ru.dbotthepony.mc.otm.recipe.UpgradeRecipe;
|
||||
@ -30,6 +31,7 @@ public class MRecipes {
|
||||
public static final MatteryRecipeType<PlatePressRecipe> PLATE_PRESS = new MatteryRecipeType<>(OverdriveThatMatters.loc(MNames.PLATE_PRESS));
|
||||
public static final MatteryRecipeType<PlatePressRecipe> ENERGY_CONTAINER = new MatteryRecipeType<>(OverdriveThatMatters.loc("energy_container"));
|
||||
public static final MatteryRecipeType<PlatePressRecipe> UPGRADE = new MatteryRecipeType<>(OverdriveThatMatters.loc("upgrade"));
|
||||
public static final MatteryRecipeType<PlatePressRecipe> HAMMER_PRIMING = new MatteryRecipeType<>(OverdriveThatMatters.loc("hammer_priming"));
|
||||
|
||||
private static final DeferredRegister<RecipeSerializer<?>> serializerRegistry = DeferredRegister.create(ForgeRegistries.RECIPE_SERIALIZERS, OverdriveThatMatters.MOD_ID);
|
||||
private static final DeferredRegister<RecipeType<?>> typeRegistry = DeferredRegister.create(ForgeRegistries.RECIPE_TYPES, OverdriveThatMatters.MOD_ID);
|
||||
@ -38,10 +40,12 @@ public class MRecipes {
|
||||
serializerRegistry.register(MNames.PLATE_PRESS, () -> PlatePressRecipeFactory.INSTANCE);
|
||||
serializerRegistry.register(ENERGY_CONTAINER.name.getPath(), () -> EnergyContainerRecipe.Companion);
|
||||
serializerRegistry.register(UPGRADE.name.getPath(), () -> UpgradeRecipe.Companion);
|
||||
serializerRegistry.register(HAMMER_PRIMING.name.getPath(), () -> ExplosiveHammerPrimingRecipe.Companion);
|
||||
|
||||
typeRegistry.register(MNames.PLATE_PRESS, () -> PLATE_PRESS);
|
||||
typeRegistry.register(ENERGY_CONTAINER.name.getPath(), () -> ENERGY_CONTAINER);
|
||||
typeRegistry.register(UPGRADE.name.getPath(), () -> UPGRADE);
|
||||
typeRegistry.register(HAMMER_PRIMING.name.getPath(), () -> HAMMER_PRIMING);
|
||||
}
|
||||
|
||||
public static void register(IEventBus bus) {
|
||||
|
@ -140,7 +140,7 @@ class ShockwaveFeature(capability: MatteryPlayerCapability) : AndroidSwitchableF
|
||||
entity.deltaMovement += (entity.position - ply.position).normalize() * (multiplier * 3.0)
|
||||
|
||||
if (ply is ServerPlayer) {
|
||||
ShockwaveDamageMobTrigger.trigger(ply as ServerPlayer, entity, source, damage)
|
||||
ShockwaveDamageMobTrigger.trigger(ply as ServerPlayer, entity, damage, source)
|
||||
}
|
||||
}
|
||||
|
||||
@ -156,7 +156,7 @@ class ShockwaveFeature(capability: MatteryPlayerCapability) : AndroidSwitchableF
|
||||
entity.deltaMovement += (entity.position - ply.position).normalize() * (multiplier * 3.0)
|
||||
|
||||
if (ply is ServerPlayer) {
|
||||
ShockwaveDamageMobTrigger.trigger(ply as ServerPlayer, entity, source, damage)
|
||||
ShockwaveDamageMobTrigger.trigger(ply as ServerPlayer, entity, damage, source)
|
||||
}
|
||||
} else {
|
||||
entity.deltaMovement += (entity.position - ply.position).normalize() * (multiplier * 6.0)
|
||||
|
@ -23,6 +23,8 @@ import net.minecraft.world.level.block.entity.BlockEntity
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType
|
||||
import net.minecraft.world.level.block.entity.RandomizableContainerBlockEntity
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.level.chunk.LevelChunk
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import net.minecraftforge.common.capabilities.Capability
|
||||
import net.minecraftforge.common.capabilities.ForgeCapabilities
|
||||
import net.minecraftforge.common.util.INBTSerializable
|
||||
@ -59,6 +61,7 @@ import ru.dbotthepony.mc.otm.onceServer
|
||||
import java.lang.ref.WeakReference
|
||||
import java.util.*
|
||||
import java.util.function.Supplier
|
||||
import java.util.stream.Stream
|
||||
import kotlin.properties.ReadWriteProperty
|
||||
import kotlin.reflect.KProperty
|
||||
import kotlin.reflect.KProperty0
|
||||
@ -730,6 +733,38 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
|
||||
|
||||
private val vec2Dir = Int2ObjectOpenHashMap<Direction>()
|
||||
|
||||
/**
|
||||
* Returns stream of players watching (tracking) specified [chunkPos] in [level]
|
||||
*/
|
||||
fun watchingPlayers(chunkPos: Long, level: Level): Stream<ServerPlayer> {
|
||||
if (level !is ServerLevel)
|
||||
return Stream.empty()
|
||||
|
||||
val subs = playerMap[level] ?: return Stream.empty()
|
||||
val chunk = subs[chunkPos] ?: return Stream.empty()
|
||||
return chunk.players.stream()
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns stream of players watching (tracking) specified [chunkPos] in [level]
|
||||
*/
|
||||
fun watchingPlayers(chunkPos: ChunkPos, level: Level) = watchingPlayers(chunkPos.toLong(), level)
|
||||
|
||||
/**
|
||||
* Returns stream of players watching (tracking) specified [blockPos] in [level]
|
||||
*/
|
||||
fun watchingPlayers(blockPos: BlockPos, level: Level) = watchingPlayers(ChunkPos(blockPos), level)
|
||||
|
||||
/**
|
||||
* Returns stream of players watching (tracking) specified [blockPos] in [level]
|
||||
*/
|
||||
fun watchingPlayers(blockPos: Vec3, level: Level) = watchingPlayers(ChunkPos.asLong(SectionPos.blockToSectionCoord(blockPos.x), SectionPos.blockToSectionCoord(blockPos.z)), level)
|
||||
|
||||
/**
|
||||
* Returns stream of players watching (tracking) specified [chunk]
|
||||
*/
|
||||
fun watchingPlayers(chunk: LevelChunk) = watchingPlayers(chunk.pos, chunk.level)
|
||||
|
||||
private fun vecKey(value: Vec3i): Int {
|
||||
if (value.x !in -1 .. 1) return -1
|
||||
if (value.y !in -1 .. 1) return -1
|
||||
|
@ -21,6 +21,8 @@ import ru.dbotthepony.mc.otm.block.BlackHoleBlock
|
||||
import ru.dbotthepony.mc.otm.block.entity.tech.GravitationStabilizerBlockEntity
|
||||
import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity
|
||||
import ru.dbotthepony.mc.otm.block.entity.blackhole.ExplosionQueue.Companion.queueForLevel
|
||||
import ru.dbotthepony.mc.otm.core.getExplosionResistance
|
||||
import ru.dbotthepony.mc.otm.core.gracefulBlockBreak
|
||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||
import ru.dbotthepony.mc.otm.core.math.plus
|
||||
import ru.dbotthepony.mc.otm.registry.MBlockEntities
|
||||
@ -101,7 +103,7 @@ class BlackHoleBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mattery
|
||||
if (setByRemote) {
|
||||
updateMass()
|
||||
}
|
||||
})
|
||||
}).property
|
||||
|
||||
fun stabilizerAttached(stabilizer: GravitationStabilizerBlockEntity) {
|
||||
if (stabilizer in stabilizers)
|
||||
@ -162,10 +164,10 @@ class BlackHoleBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mattery
|
||||
nbt["spin_direction"] = spinDirection
|
||||
}
|
||||
|
||||
override fun load(tag: CompoundTag) {
|
||||
super.load(tag)
|
||||
mass = tag.map("mass", Decimal::deserializeNBT) ?: BASELINE_MASS
|
||||
spinDirection = tag.getBoolean("spin_direction")
|
||||
override fun load(nbt: CompoundTag) {
|
||||
super.load(nbt)
|
||||
mass = nbt.map("mass", Decimal::deserializeNBT) ?: BASELINE_MASS
|
||||
spinDirection = nbt.getBoolean("spin_direction")
|
||||
}
|
||||
|
||||
var affectedBounds = BoundingBox(0, 0, 0, 1, 1, 1)
|
||||
@ -176,7 +178,7 @@ class BlackHoleBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mattery
|
||||
private fun setDeltaMovement(living: Entity, center: Vec3, distance: Double, weaker: Boolean) {
|
||||
//final double mult = Math.min(2, (30 * this.gravitation_strength) / Math.max(1, Math.pow(distance, 2)));
|
||||
// Сила притяжения
|
||||
val mult = Math.pow((1 - distance / (30 * gravitationStrength)).coerceAtLeast(0.0), 2.0) * gravitationStrength / 8
|
||||
val mult = (1 - distance / (30 * gravitationStrength)).coerceAtLeast(0.0).pow(2.0) * gravitationStrength / 8
|
||||
|
||||
// Притяжение к ядру
|
||||
val delta = living.position().vectorTo(center).normalize()
|
||||
@ -291,18 +293,7 @@ class BlackHoleBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mattery
|
||||
if (!getBlock.isAir && getBlock.block !is BlackHoleBlock) {
|
||||
val speed = getBlock.getDestroySpeed(level, pos)
|
||||
|
||||
val eResist = try {
|
||||
getBlock.getExplosionResistance(level, pos, null)
|
||||
} catch (err: NullPointerException) {
|
||||
getBlock.block.explosionResistance
|
||||
// Потому что возможно какой-либо мод не ожидает что Explosion == null
|
||||
// особенно учитывая что интерфейс IForgeBlock не имеет @ParamsAreNonnullByDefault
|
||||
// и аргумент не помечен как @Nullable
|
||||
// тем самым имеет тип Explosion! который указывается как Explosion? .. Explosion!!
|
||||
} catch (err: IllegalArgumentException) {
|
||||
getBlock.block.explosionResistance
|
||||
}
|
||||
|
||||
val eResist = getBlock.getExplosionResistance(level, pos)
|
||||
var strengthLinear = sqrt(blockPos.distSqr(pos))
|
||||
|
||||
if (strengthLinear < gravitationStrength) {
|
||||
@ -310,9 +301,7 @@ class BlackHoleBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mattery
|
||||
}
|
||||
|
||||
if (speed >= 0f && (speed * 2f).coerceAtLeast(eResist / 3f) < gravitationStrength * (12.0 / strengthLinear)) {
|
||||
Block.dropResources(getBlock, level, pos, level.getBlockEntity(pos))
|
||||
getBlock.block.destroy(level, pos, getBlock)
|
||||
level.setBlock(pos, getBlock.fluidState.createLegacyBlock(), Block.UPDATE_ALL)
|
||||
level.gracefulBlockBreak(pos, getBlock)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -98,4 +98,76 @@ object ItemsConfig : AbstractConfig("items") {
|
||||
|
||||
val FLUID_CAPSULE_CAPACITY: Int by builder.defineInRange("FLUID_CAPSULE_CAPACITY", 1000, 1, Int.MAX_VALUE)
|
||||
val FLUID_TANK_CAPACITY: Int by builder.defineInRange("FLUID_TANK_CAPACITY", 32_000, 1, Int.MAX_VALUE)
|
||||
|
||||
object ExplosiveHammer {
|
||||
val MAX_TRAVEL: Double by builder
|
||||
.comment("Max distance, in blocks, the nail can travel", "This also dictates potential max damage nail can deal (controlled by TRAVEL_DAMAGE_MULT)")
|
||||
.comment("The nail penetrate through blocks and entities, losing power in process")
|
||||
.comment("The nail can not travel into unloaded chunks and will stop immediately if it does so")
|
||||
.comment("The nail travels its entire path instantaneously")
|
||||
.defineInRange("MAX_TRAVEL", 48.0, 0.0, Double.MAX_VALUE)
|
||||
|
||||
val TRAVEL_EXPLOSION_RESIST_MULT: Double by builder
|
||||
.comment("Multiplier of explosion resistance of blocks on nail path")
|
||||
.comment("If explosion resistance multiplied by this is bigger than nail current force (base of MAX_TRAVEL)")
|
||||
.comment("then nail movement halts, otherwise nail force is reduced by explosion resistance multiplied by this")
|
||||
.comment("and block is broken (if DAMAGE_BLOCKS is true, otherwise it only acts as stopping power)")
|
||||
.comment("---")
|
||||
.comment("Values over 1 will make blocks more resistant to be penetrated through (and broken)")
|
||||
.comment("Values below 1 will make blocks less resistant to be penetrated though (and broken)")
|
||||
.comment("Value of 0 means no matter how strong block resistance is, it will be broken by nail", "(this includes bedrock!!!)")
|
||||
.comment("---")
|
||||
.defineInRange("TRAVEL_EXPLOSION_RESIST_MULT", 1.75, 0.0, Double.MAX_VALUE)
|
||||
|
||||
val TRAVEL_DAMAGE_MULT: Double by builder
|
||||
.comment("Multiplier of current nail force (base of MAX_TRAVEL) for damage values")
|
||||
.comment("That is, any being on path of nail will get damaged by nail power multiplied by this")
|
||||
.defineInRange("TRAVEL_DAMAGE_MULT", 0.6, 0.0, Double.MAX_VALUE)
|
||||
|
||||
val TRAVEL_MAX_HEALTH_MULT: Double by builder
|
||||
.comment("Multiplier of being's max health in nail path subtracted from nail force when penetrating through")
|
||||
.defineInRange("TRAVEL_MAX_HEALTH_MULT", 0.4, 0.0, Double.MAX_VALUE)
|
||||
|
||||
val DAMAGE_BLOCKS: Boolean by builder
|
||||
.comment("Should hammer (**not** explosion) damage blocks", "Blocks damaged this way will always be dropped")
|
||||
.define("DAMAGE_BLOCKS", true)
|
||||
|
||||
val EXPLOSION_DAMAGE_BLOCKS: Boolean by builder
|
||||
.comment("Should hammer **explosion** damage blocks")
|
||||
.define("EXPLOSION_DAMAGE_BLOCKS", false)
|
||||
|
||||
val FLY_OFF_CHANCE: Double by builder
|
||||
.comment("Chance that hammer will fly off hands of attacker upon impact")
|
||||
.defineInRange("FLY_OFF_CHANCE", 0.6, 0.0, 1.0)
|
||||
|
||||
val SELF_HARM_CHANCE: Double by builder
|
||||
.comment("When hammer DOES NOT fly off hands, what is chance of it damaging the user?", "(this does not account for damage because of hitting things close)", "(idiot)")
|
||||
.defineInRange("SELF_HARM_CHANCE", 0.4, 0.0, 1.0)
|
||||
|
||||
val SELF_HARM_MIN_DAMAGE: Double by builder
|
||||
.comment("When hammer DOES NOT fly off hands, what is minimal damage it deals to the user (in half of hearts)?")
|
||||
.defineInRange("SELF_HARM_MIN_DAMAGE", 2.0, 0.0, Double.MAX_VALUE)
|
||||
|
||||
val SELF_HARM_MAX_DAMAGE: Double by builder
|
||||
.comment("When hammer DOES NOT fly off hands, what is maximal damage it deals to the user (in half of hearts)?")
|
||||
.defineInRange("SELF_HARM_MAX_DAMAGE", 10.0, 0.0, Double.MAX_VALUE)
|
||||
|
||||
val FLY_OFF_DAMAGE_CHANCE: Double by builder
|
||||
.comment("When hammer flies off hands, what is chance of it damaging the user?")
|
||||
.defineInRange("FLY_OFF_DAMAGE_CHANCE", 0.8, 0.0, 1.0)
|
||||
|
||||
val FLY_OFF_MIN_DAMAGE: Double by builder
|
||||
.comment("When hammer flies off hands, what is minimal damage it deals to the user (in half of hearts)?")
|
||||
.defineInRange("FLY_OFF_MIN_DAMAGE", 4.0, 0.0, Double.MAX_VALUE)
|
||||
|
||||
val FLY_OFF_MAX_DAMAGE: Double by builder
|
||||
.comment("When hammer flies off hands, what is maximal damage it deals to the user (in half of hearts)?")
|
||||
.defineInRange("FLY_OFF_MAX_DAMAGE", 25.0, 0.0, Double.MAX_VALUE)
|
||||
}
|
||||
|
||||
init {
|
||||
builder.push("ExplosiveHammer")
|
||||
ExplosiveHammer
|
||||
builder.pop()
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,8 @@ import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.Items
|
||||
import net.minecraft.world.item.crafting.Ingredient
|
||||
import net.minecraft.world.level.BlockGetter
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.level.block.state.StateHolder
|
||||
import net.minecraft.world.level.block.state.properties.Property
|
||||
@ -220,6 +222,12 @@ fun BlockState.getExplosionResistance(level: BlockGetter, pos: BlockPos): Float
|
||||
}
|
||||
}
|
||||
|
||||
fun Level.gracefulBlockBreak(blockPos: BlockPos, block: BlockState = getBlockState(blockPos)) {
|
||||
Block.dropResources(block, this, blockPos, getBlockEntity(blockPos))
|
||||
block.block.destroy(this, blockPos, block)
|
||||
setBlock(blockPos, block.fluidState.createLegacyBlock(), Block.UPDATE_ALL)
|
||||
}
|
||||
|
||||
fun <E> MutableCollection<E>.addAll(elements: Iterator<E>) {
|
||||
for (item in elements) {
|
||||
add(item)
|
||||
|
@ -0,0 +1,210 @@
|
||||
package ru.dbotthepony.mc.otm.item
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArraySet
|
||||
import net.minecraft.ChatFormatting
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.protocol.game.ClientboundExplodePacket
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.InteractionHand
|
||||
import net.minecraft.world.damagesource.DamageSource
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.item.ItemEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.TooltipFlag
|
||||
import net.minecraft.world.level.Explosion
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.phys.AABB
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import net.minecraftforge.common.MinecraftForge
|
||||
import net.minecraftforge.event.entity.player.PlayerInteractEvent
|
||||
import net.minecraftforge.event.level.BlockEvent
|
||||
import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity
|
||||
import ru.dbotthepony.mc.otm.config.ItemsConfig
|
||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||
import ru.dbotthepony.mc.otm.core.getExplosionResistance
|
||||
import ru.dbotthepony.mc.otm.core.gracefulBlockBreak
|
||||
import ru.dbotthepony.mc.otm.core.math.component1
|
||||
import ru.dbotthepony.mc.otm.core.math.component2
|
||||
import ru.dbotthepony.mc.otm.core.math.component3
|
||||
import ru.dbotthepony.mc.otm.core.math.plus
|
||||
import ru.dbotthepony.mc.otm.core.math.times
|
||||
import ru.dbotthepony.mc.otm.core.math.toDoubleVector
|
||||
import ru.dbotthepony.mc.otm.core.nbt.set
|
||||
import ru.dbotthepony.mc.otm.core.position
|
||||
import ru.dbotthepony.mc.otm.core.tagNotNull
|
||||
import ru.dbotthepony.mc.otm.registry.HammerNailDamageSource
|
||||
import ru.dbotthepony.mc.otm.registry.MRegistry
|
||||
import ru.dbotthepony.mc.otm.triggers.NailedEntityTrigger
|
||||
|
||||
class ExplosiveHammerItem(durability: Int = 64) : Item(Properties().stacksTo(1).fireResistant().durability(durability)) {
|
||||
override fun canBeHurtBy(pDamageSource: DamageSource): Boolean {
|
||||
return super.canBeHurtBy(pDamageSource) && !pDamageSource.isExplosion
|
||||
}
|
||||
|
||||
fun isPrimed(itemStack: ItemStack): Boolean {
|
||||
return itemStack.tag?.getBoolean("primed") ?: false
|
||||
}
|
||||
|
||||
fun prime(itemStack: ItemStack) {
|
||||
itemStack.tagNotNull["primed"] = true
|
||||
}
|
||||
|
||||
fun unprime(itemStack: ItemStack) {
|
||||
if (isPrimed(itemStack))
|
||||
itemStack.tagNotNull["primed"] = false
|
||||
}
|
||||
|
||||
private val aabb = AABB(-0.1, -0.1, -0.1, 0.1, 0.1, 0.1)
|
||||
|
||||
fun attackAt(itemStack: ItemStack, attacker: LivingEntity, pos: Vec3, aim: Vec3, hand: InteractionHand) {
|
||||
if (!isPrimed(itemStack) || attacker.level.isClientSide)
|
||||
return
|
||||
|
||||
val (ex, ey, ez) = pos
|
||||
|
||||
// взрыв в месте удара молотком
|
||||
val exp = Explosion(attacker.level, attacker, ex, ey, ez, 1f, false, if (ItemsConfig.ExplosiveHammer.EXPLOSION_DAMAGE_BLOCKS) Explosion.BlockInteraction.DESTROY_WITH_DECAY else Explosion.BlockInteraction.KEEP)
|
||||
exp.explode()
|
||||
exp.finalizeExplosion(true)
|
||||
|
||||
if (!ItemsConfig.ExplosiveHammer.EXPLOSION_DAMAGE_BLOCKS)
|
||||
exp.clearToBlow()
|
||||
|
||||
val level = attacker.level as ServerLevel
|
||||
|
||||
val hitEntities = ObjectArraySet<LivingEntity>()
|
||||
hitEntities.add(attacker)
|
||||
var canTravel = ItemsConfig.ExplosiveHammer.MAX_TRAVEL
|
||||
var rayPos = pos
|
||||
var lastBlockPos: BlockPos? = null
|
||||
|
||||
// "полёт" гвоздя
|
||||
// так как у меня алгоритм "своеобразный", я изобрету велосипед ибо я такой нехороший и непослушный
|
||||
// Трассировка луча используя наивный метод
|
||||
while (canTravel > 0.0) {
|
||||
val blockPos = BlockPos(rayPos)
|
||||
|
||||
if (blockPos != lastBlockPos) {
|
||||
if (!level.hasChunkAt(blockPos)) break
|
||||
|
||||
val block = level.getBlockState(blockPos)
|
||||
|
||||
if (!block.isAir) {
|
||||
val resist = block.getExplosionResistance(level, blockPos) * ItemsConfig.ExplosiveHammer.TRAVEL_EXPLOSION_RESIST_MULT
|
||||
|
||||
if (resist >= 0.0) {
|
||||
if (resist <= canTravel) {
|
||||
canTravel -= resist
|
||||
val cond = ItemsConfig.ExplosiveHammer.DAMAGE_BLOCKS &&
|
||||
(attacker !is Player || level.mayInteract(attacker, blockPos) && !MinecraftForge.EVENT_BUS.post(BlockEvent.BreakEvent(level, blockPos, block, attacker)))
|
||||
|
||||
if (cond) {
|
||||
level.gracefulBlockBreak(blockPos, block)
|
||||
}
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lastBlockPos = blockPos
|
||||
}
|
||||
|
||||
val rayBox = aabb.move(rayPos)
|
||||
val entities = level.getEntities(null, rayBox) { it is LivingEntity && it.isAlive && !it.isSpectator && hitEntities.add(it) } as List<LivingEntity>
|
||||
val damageSource = HammerNailDamageSource(attacker, itemStack)
|
||||
|
||||
for (it in entities) {
|
||||
val damage = canTravel * ItemsConfig.ExplosiveHammer.TRAVEL_DAMAGE_MULT
|
||||
canTravel -= it.maxHealth * ItemsConfig.ExplosiveHammer.TRAVEL_MAX_HEALTH_MULT
|
||||
|
||||
it.hurt(damageSource, damage.toFloat())
|
||||
|
||||
if (attacker is ServerPlayer) {
|
||||
NailedEntityTrigger.trigger(attacker, it, damage.toFloat(), damageSource)
|
||||
}
|
||||
}
|
||||
|
||||
val delta = canTravel.coerceAtMost(0.25)
|
||||
canTravel -= delta
|
||||
rayPos += aim * delta
|
||||
}
|
||||
|
||||
MatteryBlockEntity.watchingPlayers(pos, attacker.level)
|
||||
.filter { it.position.distanceTo(pos) <= 64.0 }
|
||||
.forEach {
|
||||
it.connection.send(ClientboundExplodePacket(ex, ey, ez, 1f, exp.toBlow, exp.hitPlayers[it]))
|
||||
}
|
||||
|
||||
if (attacker !is Player || !attacker.isCreative) {
|
||||
unprime(itemStack)
|
||||
|
||||
itemStack.hurtAndBreak(1, attacker) {
|
||||
it.broadcastBreakEvent(hand)
|
||||
}
|
||||
|
||||
if (!itemStack.isEmpty && attacker.random.nextDouble() <= ItemsConfig.ExplosiveHammer.FLY_OFF_CHANCE) {
|
||||
attacker.setItemInHand(hand, ItemStack.EMPTY)
|
||||
|
||||
val (x, y, z) = attacker.position
|
||||
val entity = ItemEntity(attacker.level, x, y, z, itemStack)
|
||||
|
||||
val (xv, yv, zv) = attacker.getViewVector(0f)
|
||||
|
||||
entity.deltaMovement = Vec3(
|
||||
attacker.random.nextDouble() * xv * -0.5,
|
||||
attacker.random.nextDouble() * yv * -0.5,
|
||||
(attacker.random.nextDouble() + 0.65) * zv * -2.0,
|
||||
)
|
||||
|
||||
attacker.level.addFreshEntity(entity)
|
||||
|
||||
if (attacker.random.nextDouble() <= ItemsConfig.ExplosiveHammer.FLY_OFF_DAMAGE_CHANCE) {
|
||||
attacker.invulnerableTime = 0
|
||||
val dmg = ItemsConfig.ExplosiveHammer.FLY_OFF_MIN_DAMAGE + attacker.random.nextDouble() * (ItemsConfig.ExplosiveHammer.FLY_OFF_MAX_DAMAGE - ItemsConfig.ExplosiveHammer.FLY_OFF_MIN_DAMAGE)
|
||||
attacker.hurt(MRegistry.DAMAGE_EXPLOSIVE_HAMMER, dmg.toFloat())
|
||||
}
|
||||
} else if (attacker.random.nextDouble() <= ItemsConfig.ExplosiveHammer.SELF_HARM_CHANCE) {
|
||||
attacker.invulnerableTime = 0
|
||||
val dmg = ItemsConfig.ExplosiveHammer.SELF_HARM_MIN_DAMAGE + attacker.random.nextDouble() * (ItemsConfig.ExplosiveHammer.SELF_HARM_MAX_DAMAGE - ItemsConfig.ExplosiveHammer.SELF_HARM_MIN_DAMAGE)
|
||||
attacker.hurt(MRegistry.DAMAGE_EXPLOSIVE_HAMMER, dmg.toFloat())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun hurtEnemy(pStack: ItemStack, pTarget: LivingEntity, pAttacker: LivingEntity): Boolean {
|
||||
val aim = pAttacker.getViewVector(0f)
|
||||
val pos = pAttacker.eyePosition + aim * pTarget.position.distanceTo(pAttacker.position)
|
||||
attackAt(pStack, pAttacker, pos, aim, InteractionHand.MAIN_HAND)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun appendHoverText(pStack: ItemStack, pLevel: Level?, pTooltipComponents: MutableList<Component>, pIsAdvanced: TooltipFlag) {
|
||||
super.appendHoverText(pStack, pLevel, pTooltipComponents, pIsAdvanced)
|
||||
|
||||
pTooltipComponents.add(TranslatableComponent("$descriptionId.desc").withStyle(ChatFormatting.DARK_GRAY))
|
||||
|
||||
if (isPrimed(pStack)) {
|
||||
pTooltipComponents.add(TranslatableComponent("$descriptionId.primed").withStyle(ChatFormatting.GRAY))
|
||||
} else {
|
||||
pTooltipComponents.add(TranslatableComponent("$descriptionId.not_primed0").withStyle(ChatFormatting.GRAY))
|
||||
pTooltipComponents.add(TranslatableComponent("$descriptionId.not_primed1").withStyle(ChatFormatting.GRAY))
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun onLeftClickBlock(event: PlayerInteractEvent.LeftClickBlock) {
|
||||
val item = event.itemStack.item
|
||||
|
||||
if (item is ExplosiveHammerItem) {
|
||||
val (x, y, z) = event.pos
|
||||
item.attackAt(event.itemStack, event.entity, Vec3(x + 0.5, y + 0.5, z + 0.5), event.face?.opposite?.normal?.toDoubleVector() ?: event.entity.getViewVector(0f), event.hand)
|
||||
event.isCanceled = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,109 @@
|
||||
package ru.dbotthepony.mc.otm.recipe
|
||||
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonSyntaxException
|
||||
import net.minecraft.core.NonNullList
|
||||
import net.minecraft.data.recipes.FinishedRecipe
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.inventory.CraftingContainer
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.crafting.CraftingBookCategory
|
||||
import net.minecraft.world.item.crafting.CraftingRecipe
|
||||
import net.minecraft.world.item.crafting.Ingredient
|
||||
import net.minecraft.world.item.crafting.RecipeSerializer
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraftforge.common.Tags
|
||||
import ru.dbotthepony.mc.otm.container.stream
|
||||
import ru.dbotthepony.mc.otm.core.isActuallyEmpty
|
||||
import ru.dbotthepony.mc.otm.core.isNotEmpty
|
||||
import ru.dbotthepony.mc.otm.core.set
|
||||
import ru.dbotthepony.mc.otm.item.ExplosiveHammerItem
|
||||
import ru.dbotthepony.mc.otm.registry.MItems
|
||||
|
||||
class ExplosiveHammerPrimingRecipe(private val _id: ResourceLocation, val payload: Ingredient) : CraftingRecipe {
|
||||
override fun isIncomplete(): Boolean {
|
||||
return payload.isActuallyEmpty
|
||||
}
|
||||
|
||||
override fun getId(): ResourceLocation {
|
||||
return _id
|
||||
}
|
||||
|
||||
override fun isSpecial(): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun matches(pContainer: CraftingContainer, pLevel: Level): Boolean {
|
||||
val result = pContainer.stream().filter { it.isNotEmpty }.toList()
|
||||
if (result.size != 3) return false
|
||||
return result.any { it.item is ExplosiveHammerItem } &&
|
||||
result.any { it.`is`(Tags.Items.GUNPOWDER) } &&
|
||||
result.any { payload.test(it) }
|
||||
}
|
||||
|
||||
override fun assemble(pContainer: CraftingContainer): ItemStack {
|
||||
val hammer = pContainer.stream().filter { it.isNotEmpty && it.item is ExplosiveHammerItem }.findAny()
|
||||
if (hammer.isEmpty) return ItemStack.EMPTY
|
||||
|
||||
return hammer.orElseThrow().copyWithCount(1).also {
|
||||
(it.item as ExplosiveHammerItem).prime(it)
|
||||
}
|
||||
}
|
||||
|
||||
override fun canCraftInDimensions(pWidth: Int, pHeight: Int): Boolean {
|
||||
return pWidth * pHeight >= 3
|
||||
}
|
||||
|
||||
override fun getResultItem(): ItemStack {
|
||||
return ItemStack.EMPTY
|
||||
}
|
||||
|
||||
override fun getSerializer(): RecipeSerializer<*> {
|
||||
return Companion
|
||||
}
|
||||
|
||||
override fun category(): CraftingBookCategory {
|
||||
return CraftingBookCategory.EQUIPMENT
|
||||
}
|
||||
|
||||
override fun getIngredients(): NonNullList<Ingredient> {
|
||||
return NonNullList.of(Ingredient.of(), Ingredient.of(MItems.EXPLOSIVE_HAMMER), Ingredient.of(Tags.Items.GUNPOWDER), payload)
|
||||
}
|
||||
|
||||
val finishedRecipe = object : FinishedRecipe {
|
||||
override fun serializeRecipeData(pJson: JsonObject) {
|
||||
pJson["payload"] = payload.toJson()
|
||||
}
|
||||
|
||||
override fun getId(): ResourceLocation {
|
||||
return _id
|
||||
}
|
||||
|
||||
override fun getType(): RecipeSerializer<*> {
|
||||
return Companion
|
||||
}
|
||||
|
||||
override fun serializeAdvancement(): JsonObject? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun getAdvancementId(): ResourceLocation? {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
companion object : RecipeSerializer<ExplosiveHammerPrimingRecipe> {
|
||||
override fun fromJson(pRecipeId: ResourceLocation, pSerializedRecipe: JsonObject): ExplosiveHammerPrimingRecipe {
|
||||
return ExplosiveHammerPrimingRecipe(pRecipeId, Ingredient.fromJson(pSerializedRecipe["payload"] ?: throw JsonSyntaxException("Missing `payload` from hammer priming recipe in $pRecipeId")))
|
||||
}
|
||||
|
||||
override fun fromNetwork(pRecipeId: ResourceLocation, pBuffer: FriendlyByteBuf): ExplosiveHammerPrimingRecipe {
|
||||
return ExplosiveHammerPrimingRecipe(pRecipeId, Ingredient.fromNetwork(pBuffer))
|
||||
}
|
||||
|
||||
override fun toNetwork(pBuffer: FriendlyByteBuf, pRecipe: ExplosiveHammerPrimingRecipe) {
|
||||
pRecipe.payload.toNetwork(pBuffer)
|
||||
}
|
||||
}
|
||||
}
|
@ -146,6 +146,9 @@ internal fun addMainCreativeTabItems(consumer: CreativeModeTab.Output) {
|
||||
energized(MItems.ENERGY_SWORD)
|
||||
energized(MItems.PLASMA_RIFLE)
|
||||
|
||||
accept(MItems.EXPLOSIVE_HAMMER)
|
||||
accept(ItemStack(MItems.EXPLOSIVE_HAMMER).also { MItems.EXPLOSIVE_HAMMER.prime(it) })
|
||||
|
||||
accept(MItems.BLACK_HOLE_SCANNER)
|
||||
accept(MItems.GRAVITATION_FIELD_LIMITER)
|
||||
accept(MItems.GRAVITATION_FIELD_SENSOR)
|
||||
|
@ -184,3 +184,9 @@ class PlasmaDamageSource(entity: Entity? = null, inflictor: ItemStack? = null) :
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
class HammerNailDamageSource(entity: Entity? = null, inflictor: ItemStack? = null) : MatteryDamageSource(MRegistry.DAMAGE_HAMMER_NAIL_NAME, entity, inflictor) {
|
||||
override fun scalesWithDifficulty(): Boolean {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
@ -215,6 +215,8 @@ object MItems {
|
||||
::TRITANIUM_BOOTS
|
||||
)
|
||||
|
||||
val EXPLOSIVE_HAMMER: ExplosiveHammerItem by registry.register("explosive_hammer") { ExplosiveHammerItem() }
|
||||
|
||||
val ENERGY_SWORD: Item by registry.register(MNames.ENERGY_SWORD) { EnergySwordItem() }
|
||||
|
||||
val PLASMA_RIFLE: Item by registry.register(MNames.PLASMA_RIFLE) { PlasmaRifleItem() }
|
||||
|
@ -44,6 +44,7 @@ import ru.dbotthepony.mc.otm.triggers.BecomeHumaneTrigger
|
||||
import ru.dbotthepony.mc.otm.triggers.BlackHoleTrigger
|
||||
import ru.dbotthepony.mc.otm.triggers.EnderTeleporterFallDeathTrigger
|
||||
import ru.dbotthepony.mc.otm.triggers.FallDampenersSaveTrigger
|
||||
import ru.dbotthepony.mc.otm.triggers.NailedEntityTrigger
|
||||
import ru.dbotthepony.mc.otm.triggers.NanobotsArmorTrigger
|
||||
import ru.dbotthepony.mc.otm.triggers.ShockwaveDamageMobTrigger
|
||||
import ru.dbotthepony.mc.otm.triggers.ShockwaveTrigger
|
||||
@ -195,6 +196,8 @@ object MRegistry {
|
||||
const val DAMAGE_SHOCKWAVE_NAME = "otm_shockwave"
|
||||
const val DAMAGE_PLASMA_NAME = "otm_plasma"
|
||||
const val DAMAGE_COSMIC_RAYS_NAME = "otm_cosmic_rays"
|
||||
const val DAMAGE_EXPLOSIVE_HAMMER_NAME = "otm_explosive_hammer"
|
||||
const val DAMAGE_HAMMER_NAIL_NAME = "otm_hammer_nail"
|
||||
|
||||
val DAMAGE_EXOPACK_PROBE = ImmutableDamageSource(DamageSource(DAMAGE_EXOPACK_PROBE_ID).bypassArmor().bypassMagic())
|
||||
|
||||
@ -203,6 +206,7 @@ object MRegistry {
|
||||
val DAMAGE_EVENT_HORIZON = ImmutableDamageSource(DamageSource(DAMAGE_EVENT_HORIZON_ID).bypassMagic().bypassArmor())
|
||||
val DAMAGE_HAWKING_RADIATION = ImmutableDamageSource(DamageSource(DAMAGE_HAWKING_RADIATION_ID))
|
||||
val DAMAGE_COSMIC_RAYS = ImmutableDamageSource(DamageSource(DAMAGE_COSMIC_RAYS_NAME).bypassArmor().bypassMagic())
|
||||
val DAMAGE_EXPLOSIVE_HAMMER = ImmutableDamageSource(DamageSource(DAMAGE_EXPLOSIVE_HAMMER_NAME))
|
||||
|
||||
val DAMAGE_EMP: DamageSource = ImmutableDamageSource(EMPDamageSource())
|
||||
|
||||
@ -270,6 +274,7 @@ object MRegistry {
|
||||
CriteriaTriggers.register(EnderTeleporterFallDeathTrigger)
|
||||
CriteriaTriggers.register(KillAsAndroidTrigger)
|
||||
CriteriaTriggers.register(AndroidTravelUnderwater)
|
||||
CriteriaTriggers.register(NailedEntityTrigger)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,61 @@
|
||||
package ru.dbotthepony.mc.otm.triggers
|
||||
|
||||
import com.google.gson.JsonObject
|
||||
import net.minecraft.advancements.critereon.AbstractCriterionTriggerInstance
|
||||
import net.minecraft.advancements.critereon.DamagePredicate
|
||||
import net.minecraft.advancements.critereon.DamageSourcePredicate
|
||||
import net.minecraft.advancements.critereon.DeserializationContext
|
||||
import net.minecraft.advancements.critereon.EntityPredicate
|
||||
import net.minecraft.advancements.critereon.MinMaxBounds
|
||||
import net.minecraft.advancements.critereon.SerializationContext
|
||||
import net.minecraft.advancements.critereon.SimpleCriterionTrigger
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.damagesource.DamageSource
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import ru.dbotthepony.mc.otm.core.set
|
||||
|
||||
abstract class HurtTrigger : SimpleCriterionTrigger<HurtTrigger.Instance>() {
|
||||
abstract val ID: ResourceLocation
|
||||
|
||||
override fun getId(): ResourceLocation {
|
||||
return ID
|
||||
}
|
||||
|
||||
override fun createInstance(
|
||||
p_66248_: JsonObject,
|
||||
p_66249_: EntityPredicate.Composite,
|
||||
p_66250_: DeserializationContext
|
||||
): Instance {
|
||||
return Instance(
|
||||
EntityPredicate.Composite.fromJson(p_66248_, "entity_predicate", p_66250_),
|
||||
(p_66248_["damage"] as? JsonObject)?.let(DamagePredicate::fromJson) ?: DamagePredicate.ANY
|
||||
)
|
||||
}
|
||||
|
||||
fun trigger(player: ServerPlayer, entity: LivingEntity, damage: Float, damageSource: DamageSource) {
|
||||
val context = EntityPredicate.createContext(player, entity)
|
||||
|
||||
trigger(player) {
|
||||
it.predicate.matches(context) && it.damagePredicate.matches(player, damageSource, damage, damage, false)
|
||||
}
|
||||
}
|
||||
|
||||
inner class Instance(
|
||||
val predicate: EntityPredicate.Composite = EntityPredicate.Composite.ANY,
|
||||
val damagePredicate: DamagePredicate = DamagePredicate(
|
||||
MinMaxBounds.Doubles.atLeast(1.0),
|
||||
MinMaxBounds.Doubles.atLeast(1.0),
|
||||
EntityPredicate.ANY,
|
||||
null,
|
||||
DamageSourcePredicate.ANY
|
||||
)
|
||||
) : AbstractCriterionTriggerInstance(ID, EntityPredicate.Composite.ANY) {
|
||||
override fun serializeToJson(pConditions: SerializationContext): JsonObject {
|
||||
return super.serializeToJson(pConditions).also {
|
||||
it["entity_predicate"] = predicate.toJson(pConditions)
|
||||
it["damage"] = damagePredicate.serializeToJson()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package ru.dbotthepony.mc.otm.triggers
|
||||
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||
|
||||
object NailedEntityTrigger : HurtTrigger() {
|
||||
override val ID = ResourceLocation(OverdriveThatMatters.MOD_ID, "hammer_nail_damage")
|
||||
}
|
@ -1,63 +1,8 @@
|
||||
package ru.dbotthepony.mc.otm.triggers
|
||||
|
||||
import com.google.gson.JsonObject
|
||||
import net.minecraft.advancements.critereon.AbstractCriterionTriggerInstance
|
||||
import net.minecraft.advancements.critereon.DamagePredicate
|
||||
import net.minecraft.advancements.critereon.DamageSourcePredicate
|
||||
import net.minecraft.advancements.critereon.DeserializationContext
|
||||
import net.minecraft.advancements.critereon.EntityPredicate
|
||||
import net.minecraft.advancements.critereon.MinMaxBounds
|
||||
import net.minecraft.advancements.critereon.SerializationContext
|
||||
import net.minecraft.advancements.critereon.SimpleCriterionTrigger
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.damagesource.DamageSource
|
||||
import net.minecraft.world.entity.Entity
|
||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||
import ru.dbotthepony.mc.otm.core.nbt.set
|
||||
import ru.dbotthepony.mc.otm.core.set
|
||||
|
||||
object ShockwaveDamageMobTrigger: SimpleCriterionTrigger<ShockwaveDamageMobTrigger.Instance>() {
|
||||
val ID = ResourceLocation(OverdriveThatMatters.MOD_ID, "shockwave_damage_mob")
|
||||
|
||||
override fun getId(): ResourceLocation {
|
||||
return ID
|
||||
}
|
||||
|
||||
override fun createInstance(
|
||||
p_66248_: JsonObject,
|
||||
p_66249_: EntityPredicate.Composite,
|
||||
p_66250_: DeserializationContext
|
||||
): Instance {
|
||||
return Instance(
|
||||
EntityPredicate.Composite.fromJson(p_66248_, "entity_predicate", p_66250_),
|
||||
(p_66248_["damage"] as? JsonObject)?.let(DamagePredicate::fromJson) ?: DamagePredicate.ANY
|
||||
)
|
||||
}
|
||||
|
||||
fun trigger(player: ServerPlayer, entity: Entity, damageSource: DamageSource, damage: Float) {
|
||||
val context = EntityPredicate.createContext(player, entity)
|
||||
|
||||
trigger(player) {
|
||||
it.predicate.matches(context) && it.damagePredicate.matches(player, damageSource, damage, damage, false)
|
||||
}
|
||||
}
|
||||
|
||||
class Instance(
|
||||
val predicate: EntityPredicate.Composite = EntityPredicate.Composite.ANY,
|
||||
val damagePredicate: DamagePredicate = DamagePredicate(
|
||||
MinMaxBounds.Doubles.atLeast(1.0),
|
||||
MinMaxBounds.Doubles.atLeast(1.0),
|
||||
EntityPredicate.ANY,
|
||||
null,
|
||||
DamageSourcePredicate.ANY
|
||||
)
|
||||
) : AbstractCriterionTriggerInstance(ID, EntityPredicate.Composite.ANY) {
|
||||
override fun serializeToJson(p_16979_: SerializationContext): JsonObject {
|
||||
return super.serializeToJson(p_16979_).also {
|
||||
it["entity_predicate"] = predicate.toJson(p_16979_)
|
||||
it["damage"] = damagePredicate.serializeToJson()
|
||||
}
|
||||
}
|
||||
}
|
||||
object ShockwaveDamageMobTrigger : HurtTrigger() {
|
||||
override val ID = ResourceLocation(OverdriveThatMatters.MOD_ID, "shockwave_damage_mob")
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user