Skip to content

Commit

Permalink
Implement conditional damage boost modifier serializer
Browse files Browse the repository at this point in the history
  • Loading branch information
KnightMiner committed Apr 15, 2022
1 parent 2c97314 commit 388adf7
Show file tree
Hide file tree
Showing 16 changed files with 240 additions and 153 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"type": "tconstruct:conditional_damage",
"predicate": {
"type": "tconstruct:mob_type",
"mobs": "minecraft:water"
},
"damage": 2.0
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"type": "tconstruct:conditional_damage",
"predicate": {
"type": "tconstruct:or",
"predicates": [
{
"type": "tconstruct:mob_type",
"mobs": "minecraft:arthropod"
},
{
"type": "tconstruct:tag",
"tag": "forge:creepers"
}
]
},
"damage": 2.0,
"effect": {
"name": "minecraft:slowness",
"level": 4
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "tconstruct:conditional_damage",
"predicate": {
"type": "tconstruct:fire_immune"
},
"damage": 1.6
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"type": "tconstruct:conditional_damage",
"predicate": {
"type": "tconstruct:or",
"predicates": [
{
"type": "tconstruct:mob_type",
"mobs": "minecraft:illager"
},
{
"type": "tconstruct:tag",
"tag": "forge:villagers"
}
]
},
"damage": 2.0
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"type": "tconstruct:conditional_damage",
"predicate": {
"type": "tconstruct:mob_type",
"mobs": "minecraft:undead"
},
"damage": 2.0
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package slimeknights.tconstruct.library.modifiers.dynamic;

import com.google.gson.JsonObject;
import lombok.RequiredArgsConstructor;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.Component;
import net.minecraft.util.GsonHelper;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.TooltipFlag;
import net.minecraftforge.registries.ForgeRegistries;
import slimeknights.mantle.data.GenericLoaderRegistry.IGenericLoader;
import slimeknights.tconstruct.library.json.predicate.IJsonPredicate;
import slimeknights.tconstruct.library.json.predicate.entity.LivingEntityPredicate;
import slimeknights.tconstruct.library.modifiers.Modifier;
import slimeknights.tconstruct.library.modifiers.impl.IncrementalModifier;
import slimeknights.tconstruct.library.tools.context.ToolAttackContext;
import slimeknights.tconstruct.library.tools.nbt.IToolStackView;
import slimeknights.tconstruct.library.tools.stat.ToolStats;
import slimeknights.tconstruct.library.utils.JsonUtils;
import slimeknights.tconstruct.library.utils.TooltipKey;

import javax.annotation.Nullable;
import java.util.List;
import java.util.Objects;

/** Modifier that boosts damage against a conditional mob, applying an optional potion effect */
@RequiredArgsConstructor
public class ConditionalDamageModifier extends IncrementalModifier {
/** Requirement for entities to match */
private final IJsonPredicate<LivingEntity> predicate;
/** Damage bonus */
private final float damage;
/** Optional effect to add */
@Nullable
private final MobEffect effect;
/** Optional effect level */
private final int effectLevel;

public ConditionalDamageModifier(IJsonPredicate<LivingEntity> predicate, float damage) {
this(predicate, damage, null, 0);
}

@Override
public float getEntityDamage(IToolStackView tool, int level, ToolAttackContext context, float baseDamage, float damage) {
LivingEntity target = context.getLivingTarget();
if (target != null && predicate.matches(target)) {
damage += getScaledLevel(tool, level) * damage * tool.getMultiplier(ToolStats.ATTACK_DAMAGE);
}
return damage;
}

@Override
public void addInformation(IToolStackView tool, int level, @Nullable Player player, List<Component> tooltip, TooltipKey tooltipKey, TooltipFlag tooltipFlag) {
addDamageTooltip(tool, level, damage, tooltip);
}

@Override
public int afterEntityHit(IToolStackView tool, int level, ToolAttackContext context, float damageDealt) {
if (effect != null) {
LivingEntity target = context.getLivingTarget();
if (target != null && predicate.matches(target)) {
int duration = 20;
int maxBonus = (int)(10 * getScaledLevel(tool, level));
if (maxBonus > 0) {
duration += context.getAttacker().getRandom().nextInt(maxBonus);
}
target.addEffect(new MobEffectInstance(effect, duration, effectLevel - 1));
}
}
return 0;
}

@Override
public IGenericLoader<? extends Modifier> getLoader() {
return LOADER;
}

/** Loader for this modifier */
public static final IGenericLoader<ConditionalDamageModifier> LOADER = new IGenericLoader<>() {
@Override
public ConditionalDamageModifier deserialize(JsonObject json) {
IJsonPredicate<LivingEntity> predicate = LivingEntityPredicate.LOADER.getAndDeserialize(json, "predicate");
float damage = GsonHelper.getAsFloat(json, "damage");
MobEffect effect = null;
int level = 0;
if (json.has("effect")) {
JsonObject effectJson = GsonHelper.getAsJsonObject(json, "effect");
effect = JsonUtils.getAsEntry(ForgeRegistries.MOB_EFFECTS, effectJson, "name");
level = JsonUtils.getIntMin(effectJson, "level", 1);
}
return new ConditionalDamageModifier(predicate, damage, effect, level);
}

@Override
public void serialize(ConditionalDamageModifier object, JsonObject json) {
json.add("predicate", LivingEntityPredicate.LOADER.serialize(object.predicate));
json.addProperty("damage", object.damage);
if (object.effect != null && object.effectLevel > 0) {
JsonObject effectJson = new JsonObject();
effectJson.addProperty("name", Objects.requireNonNull(object.effect.getRegistryName()).toString());
effectJson.addProperty("level", object.effectLevel);
json.add("effect", effectJson);
}
}

@Override
public ConditionalDamageModifier fromNetwork(FriendlyByteBuf buffer) {
IJsonPredicate<LivingEntity> predicate = LivingEntityPredicate.LOADER.fromNetwork(buffer);
float damage = buffer.readFloat();
MobEffect effect = null;
int level = buffer.readVarInt();
if (level > 0) {
effect = buffer.readRegistryIdUnsafe(ForgeRegistries.MOB_EFFECTS);
}
return new ConditionalDamageModifier(predicate, damage, effect, level);
}

@Override
public void toNetwork(ConditionalDamageModifier object, FriendlyByteBuf buffer) {
LivingEntityPredicate.LOADER.toNetwork(object.predicate, buffer);
buffer.writeFloat(object.damage);
if (object.effectLevel > 0 && object.effect != null) {
buffer.writeVarInt(object.effectLevel);
buffer.writeRegistryIdUnsafe(ForgeRegistries.MOB_EFFECTS, object.effect);
} else {
buffer.writeVarInt(0);
}
}
};
}
12 changes: 2 additions & 10 deletions src/main/java/slimeknights/tconstruct/tools/TinkerModifiers.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.world.effect.MobEffectCategory;
import net.minecraft.world.entity.MobType;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.Rarity;
import net.minecraft.world.item.crafting.Ingredient;
Expand All @@ -29,6 +28,7 @@
import slimeknights.tconstruct.library.modifiers.Modifier;
import slimeknights.tconstruct.library.modifiers.ModifierId;
import slimeknights.tconstruct.library.modifiers.ModifierManager;
import slimeknights.tconstruct.library.modifiers.dynamic.ConditionalDamageModifier;
import slimeknights.tconstruct.library.modifiers.dynamic.ExtraModifier;
import slimeknights.tconstruct.library.modifiers.dynamic.MobDisguiseModifier;
import slimeknights.tconstruct.library.modifiers.dynamic.StatBoostModifier;
Expand Down Expand Up @@ -183,15 +183,11 @@
import slimeknights.tconstruct.tools.modifiers.upgrades.harvest.HasteModifier;
import slimeknights.tconstruct.tools.modifiers.upgrades.harvest.HydraulicModifier;
import slimeknights.tconstruct.tools.modifiers.upgrades.harvest.LightspeedModifier;
import slimeknights.tconstruct.tools.modifiers.upgrades.melee.BaneOfSssssModifier;
import slimeknights.tconstruct.tools.modifiers.upgrades.melee.CoolingModifier;
import slimeknights.tconstruct.tools.modifiers.upgrades.melee.FieryModifier;
import slimeknights.tconstruct.tools.modifiers.upgrades.melee.KillagerModifier;
import slimeknights.tconstruct.tools.modifiers.upgrades.melee.KnockbackModifier;
import slimeknights.tconstruct.tools.modifiers.upgrades.melee.LootingModifier;
import slimeknights.tconstruct.tools.modifiers.upgrades.melee.PaddedModifier;
import slimeknights.tconstruct.tools.modifiers.upgrades.melee.PiercingModifier;
import slimeknights.tconstruct.tools.modifiers.upgrades.melee.ScaledTypeDamageModifier;
import slimeknights.tconstruct.tools.modifiers.upgrades.melee.SeveringModifier;
import slimeknights.tconstruct.tools.modifiers.upgrades.melee.SharpnessModifier;
import slimeknights.tconstruct.tools.modifiers.upgrades.melee.SweepingEdgeModifier;
Expand Down Expand Up @@ -274,11 +270,6 @@ public TinkerModifiers() {

// damage boost
public static final StaticModifier<PiercingModifier> piercing = MODIFIERS.register("piercing", PiercingModifier::new);
public static final StaticModifier<ScaledTypeDamageModifier> smite = MODIFIERS.register("smite", () -> new ScaledTypeDamageModifier(MobType.UNDEAD));
public static final StaticModifier<BaneOfSssssModifier> baneOfSssss = MODIFIERS.register("bane_of_sssss", BaneOfSssssModifier::new);
public static final StaticModifier<ScaledTypeDamageModifier> antiaquatic = MODIFIERS.register("antiaquatic", () -> new ScaledTypeDamageModifier(MobType.WATER));
public static final StaticModifier<KillagerModifier> killager = MODIFIERS.register("killager", KillagerModifier::new);
public static final StaticModifier<CoolingModifier> cooling = MODIFIERS.register("cooling", CoolingModifier::new);
public static final StaticModifier<SharpnessModifier> sharpness = MODIFIERS.register("sharpness", SharpnessModifier::new);
public static final StaticModifier<SweepingEdgeModifier> sweeping = MODIFIERS.register("sweeping_edge", SweepingEdgeModifier::new);

Expand Down Expand Up @@ -496,6 +487,7 @@ void registerSerializers(RegistryEvent.Register<RecipeSerializer<?>> event) {
ModifierManager.MODIFIER_LOADERS.register(TConstruct.getResource("stat_boost"), StatBoostModifier.LOADER);
ModifierManager.MODIFIER_LOADERS.register(TConstruct.getResource("extra_slot"), ExtraModifier.LOADER);
ModifierManager.MODIFIER_LOADERS.register(TConstruct.getResource("mob_disguise"), MobDisguiseModifier.LOADER);
ModifierManager.MODIFIER_LOADERS.register(TConstruct.getResource("conditional_damage"), ConditionalDamageModifier.LOADER);
}

@SubscribeEvent
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@ public class ModifierIds {
// general abilities
public static final ModifierId reach = id("reach");

// damage boost
public static final ModifierId smite = id("smite");
public static final ModifierId baneOfSssss = id("bane_of_sssss");
public static final ModifierId antiaquatic = id("antiaquatic");
public static final ModifierId killager = id("killager");
public static final ModifierId cooling = id("cooling");

// armor
public static final ModifierId wings = id("wings");
public static final ModifierId knockbackResistance = id("knockback_resistance");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
package slimeknights.tconstruct.tools.data;

import net.minecraft.data.DataGenerator;
import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.MobType;
import net.minecraft.world.entity.ai.attributes.AttributeModifier.Operation;
import net.minecraft.world.entity.ai.attributes.Attributes;
import net.minecraft.world.item.Rarity;
import net.minecraft.world.item.Tiers;
import net.minecraftforge.common.ForgeMod;
import slimeknights.tconstruct.common.TinkerTags;
import slimeknights.tconstruct.library.data.tinkering.AbstractModifierProvider;
import slimeknights.tconstruct.library.json.predicate.entity.LivingEntityPredicate;
import slimeknights.tconstruct.library.json.predicate.entity.MobTypePredicate;
import slimeknights.tconstruct.library.json.predicate.entity.TagEntityPredicate;
import slimeknights.tconstruct.library.modifiers.Modifier;
import slimeknights.tconstruct.library.modifiers.dynamic.ConditionalDamageModifier;
import slimeknights.tconstruct.library.modifiers.dynamic.ExtraModifier;
import slimeknights.tconstruct.library.modifiers.dynamic.MobDisguiseModifier;
import slimeknights.tconstruct.library.modifiers.dynamic.StatBoostModifier;
Expand Down Expand Up @@ -80,6 +87,16 @@ protected void addModifiers() {
// general abilities
addModifier(ModifierIds.reach, StatBoostModifier.builder().attribute("tconstruct.modifier.reach", ForgeMod.REACH_DISTANCE.get(), Operation.ADDITION, 1, EquipmentSlot.MAINHAND, EquipmentSlot.HEAD, EquipmentSlot.CHEST, EquipmentSlot.LEGS, EquipmentSlot.FEET).build());

// damage boost
addModifier(ModifierIds.smite, new ConditionalDamageModifier(new MobTypePredicate(MobType.UNDEAD), 2.0f));
addModifier(ModifierIds.antiaquatic, new ConditionalDamageModifier(new MobTypePredicate(MobType.WATER), 2.0f));
addModifier(ModifierIds.cooling, new ConditionalDamageModifier(LivingEntityPredicate.FIRE_IMMUNE, 1.6f));
addModifier(ModifierIds.baneOfSssss, new ConditionalDamageModifier(
LivingEntityPredicate.OR.create(new MobTypePredicate(MobType.ARTHROPOD), new TagEntityPredicate(TinkerTags.EntityTypes.CREEPERS)),
2.0f, MobEffects.MOVEMENT_SLOWDOWN, 4));
addModifier(ModifierIds.killager, new ConditionalDamageModifier(
LivingEntityPredicate.OR.create(new MobTypePredicate(MobType.ILLAGER), new TagEntityPredicate(TinkerTags.EntityTypes.VILLAGERS)), 2.0f));

// armor
addModifier(TinkerModifiers.golden, StatBoostModifier.builder().addFlag(ModifiableArmorItem.PIGLIN_NEUTRAL).build());
addModifier(ModifierIds.wings, StatBoostModifier.builder().addFlag(ModifiableArmorItem.ELYTRA).build());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -466,55 +466,55 @@ private void addModifierRecipes(Consumer<FinishedRecipe> consumer) {
.setSlots(SlotType.UPGRADE, 1)
.saveSalvage(consumer, prefix(TinkerModifiers.piercing, upgradeSalvage))
.save(consumer, prefix(TinkerModifiers.piercing, upgradeFolder));
IncrementalModifierRecipeBuilder.modifier(TinkerModifiers.smite)
IncrementalModifierRecipeBuilder.modifier(ModifierIds.smite)
.setTools(TinkerTags.Items.MELEE)
.setInputSalvage(Items.GLISTERING_MELON_SLICE, 1, 5, false)
.setMaxLevel(5) // +12.5 undead damage
.setSlots(SlotType.UPGRADE, 1)
.includeUnarmed()
.saveSalvage(consumer, prefix(TinkerModifiers.smite, upgradeSalvage))
.save(consumer, prefix(TinkerModifiers.smite, upgradeFolder));
IncrementalModifierRecipeBuilder.modifier(TinkerModifiers.baneOfSssss)
.saveSalvage(consumer, prefix(ModifierIds.smite, upgradeSalvage))
.save(consumer, prefix(ModifierIds.smite, upgradeFolder));
IncrementalModifierRecipeBuilder.modifier(ModifierIds.baneOfSssss)
.setTools(TinkerTags.Items.MELEE)
.setInputSalvage(Items.FERMENTED_SPIDER_EYE, 1, 15, false)
.setMaxLevel(5) // +12.5 spider damage
.setSlots(SlotType.UPGRADE, 1)
.includeUnarmed()
.saveSalvage(consumer, prefix(TinkerModifiers.baneOfSssss, upgradeSalvage))
.save(consumer, prefix(TinkerModifiers.baneOfSssss, upgradeFolder));
IncrementalModifierRecipeBuilder.modifier(TinkerModifiers.antiaquatic)
.saveSalvage(consumer, prefix(ModifierIds.baneOfSssss, upgradeSalvage))
.save(consumer, prefix(ModifierIds.baneOfSssss, upgradeFolder));
IncrementalModifierRecipeBuilder.modifier(ModifierIds.antiaquatic)
.setTools(TinkerTags.Items.MELEE)
.setInputSalvage(Items.PUFFERFISH, 1, 20, false)
.setMaxLevel(5) // +12.5 fish damage
.setSlots(SlotType.UPGRADE, 1)
.includeUnarmed()
.saveSalvage(consumer, prefix(TinkerModifiers.antiaquatic, upgradeSalvage))
.save(consumer, prefix(TinkerModifiers.antiaquatic, upgradeFolder));
IncrementalModifierRecipeBuilder.modifier(TinkerModifiers.cooling)
.saveSalvage(consumer, prefix(ModifierIds.antiaquatic, upgradeSalvage))
.save(consumer, prefix(ModifierIds.antiaquatic, upgradeFolder));
IncrementalModifierRecipeBuilder.modifier(ModifierIds.cooling)
.setTools(TinkerTags.Items.MELEE)
.setInputSalvage(Items.PRISMARINE_CRYSTALS, 1, 25, false)
.setMaxLevel(5) // +10 fire mob damage
.setSlots(SlotType.UPGRADE, 1)
.includeUnarmed()
.saveSalvage(consumer, prefix(TinkerModifiers.cooling, upgradeSalvage))
.save(consumer, prefix(TinkerModifiers.cooling, upgradeFolder));
.saveSalvage(consumer, prefix(ModifierIds.cooling, upgradeSalvage))
.save(consumer, prefix(ModifierIds.cooling, upgradeFolder));
// killager uses both types of lapis
IncrementalModifierRecipeBuilder.modifier(TinkerModifiers.killager)
IncrementalModifierRecipeBuilder.modifier(ModifierIds.killager)
.setTools(TinkerTags.Items.MELEE)
.setInput(Tags.Items.GEMS_LAPIS, 1, 45)
.setSalvage(Items.LAPIS_LAZULI, 15, false)
.setMaxLevel(5) // +12.5 illager damage
.setSlots(SlotType.UPGRADE, 1)
.includeUnarmed()
.saveSalvage(consumer, prefix(TinkerModifiers.killager, upgradeSalvage))
.save(consumer, wrap(TinkerModifiers.killager, upgradeFolder, "_from_dust"));
IncrementalModifierRecipeBuilder.modifier(TinkerModifiers.killager)
.saveSalvage(consumer, prefix(ModifierIds.killager, upgradeSalvage))
.save(consumer, wrap(ModifierIds.killager, upgradeFolder, "_from_dust"));
IncrementalModifierRecipeBuilder.modifier(ModifierIds.killager)
.setTools(TinkerTags.Items.MELEE)
.setInput(Tags.Items.STORAGE_BLOCKS_LAPIS, 9, 45)
.setMaxLevel(5) // +12.5 illager damage
.setSlots(SlotType.UPGRADE, 1)
.includeUnarmed()
.save(consumer, wrap(TinkerModifiers.killager, upgradeFolder, "_from_block"));
.save(consumer, wrap(ModifierIds.killager, upgradeFolder, "_from_block"));
// sharpness can use shards or blocks
IncrementalModifierRecipeBuilder.modifier(TinkerModifiers.sharpness)
.setTools(TinkerTags.Items.MELEE)
Expand Down

0 comments on commit 388adf7

Please sign in to comment.